From b4be08c7d1cf9e0339b16f99059ba72ea82a3930 Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Fri, 15 Mar 2024 19:33:10 -0400 Subject: [PATCH 01/86] blank project --- .gitignore | 1 - DevTextFiles/CODER_NOTES.txt | 22 --- DevTextFiles/Todo_Tigran.txt | 1 - LICENSE | 2 +- README.md | 17 +- TEST.md | 5 - docs/contributing.md | 8 +- .../ShowcaseExperience.txt | 58 ------ icon.svg.import | 2 +- project.godot | 39 +--- src/resources/gitnoremove.md | 0 src/special_scenes/game_handler.tscn | 68 ------- src/special_scripts/inside_maze.gd | 178 ------------------ src/special_scripts/outside_maze.gd | 47 ----- src/static_scripts/gitnoremove.md | 0 src/testing/from_old_projects/super_menu.gd | 42 ----- src/testing/test_space.gd | 117 ------------ src/testing/test_space.tscn | 6 - 18 files changed, 13 insertions(+), 600 deletions(-) delete mode 100644 DevTextFiles/CODER_NOTES.txt delete mode 100644 DevTextFiles/Todo_Tigran.txt delete mode 100644 TEST.md delete mode 100644 docs/file_exparimentation/ShowcaseExperience.txt delete mode 100644 src/resources/gitnoremove.md delete mode 100644 src/special_scenes/game_handler.tscn delete mode 100644 src/special_scripts/inside_maze.gd delete mode 100644 src/special_scripts/outside_maze.gd delete mode 100644 src/static_scripts/gitnoremove.md delete mode 100644 src/testing/from_old_projects/super_menu.gd delete mode 100644 src/testing/test_space.gd delete mode 100644 src/testing/test_space.tscn diff --git a/.gitignore b/.gitignore index f89d046..4709183 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ # Godot 4+ specific ignores .godot/ -.vscode/ \ No newline at end of file diff --git a/DevTextFiles/CODER_NOTES.txt b/DevTextFiles/CODER_NOTES.txt deleted file mode 100644 index 6342406..0000000 --- a/DevTextFiles/CODER_NOTES.txt +++ /dev/null @@ -1,22 +0,0 @@ - -ROADMAP: - Make the Maze a playable single player experience - Make the Maze look pretty - Make the Maze have cool thematic things - Make the level editing work - Make the multiplayer work - -Next: (Crtl+Shift+F "###" to find things that need to be worked on) - Look at Godot top down shooter tutorial to see how walls are done - Rework customization settings from Fragile bounds - Grab my file reading code. MAKE SURE I CLOSE MY FILES!! FOR SAFETY!! In TestSpace: - I need to have a way to throw errors somehow like what if someone makes there be 26 rooms - maybe a tile can have multiple things, like a transfer function and something that looks like an exit - Figure out Transfer functions - Make the Maze movement read: - Rooms - To make walls and circuits work - Circuits - Ok my file legend should also have "Observers" that the can activate circuits - Add basic art - Add some juicy sounds - diff --git a/DevTextFiles/Todo_Tigran.txt b/DevTextFiles/Todo_Tigran.txt deleted file mode 100644 index 37ef05a..0000000 --- a/DevTextFiles/Todo_Tigran.txt +++ /dev/null @@ -1 +0,0 @@ -Make the game playable diff --git a/LICENSE b/LICENSE index cf6dca5..e07a8d0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Tigran +Copyright (c) 2023 Scrimblosoft Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index b27ff06..46af03f 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,16 @@ # The-Maze-With-GDYU A collaborative experiment between GDYU friends. CURRENTLY: - - -Deciding a ticket system to make it easy to know how to help - - -Setting systems for contribution - - -Deciding how to iterate on gameplay + - Prototyping all our gameplay mechanics, pick an task from the [Project Board](https://github.com/orgs/GDYUClub/projects/1) if you'd like to help - Here's a [video](https://youtu.be/xjZsrdWe2jU) to understand what this is! - -Here's the [design doc](https://docs.google.com/document/d/1vs-uuo3EVE-bTyuviN5FSpdkm3ZyLSNCJJKOx5uJOF0/edit#heading=h.1jqugjgd3he3) to help contribute! +Here's a [video](https://youtu.be/xjZsrdWe2jU) to understand what this is! -Read [contributing.md](/docs/contributing.md) before working on the repository. +Here's the [design doc](https://docs.google.com/document/d/1vs-uuo3EVE-bTyuviN5FSpdkm3ZyLSNCJJKOx5uJOF0/edit#heading=h.1jqugjgd3he3) to help contribute! -DUE MAY 31 2024 23:59 +Read [contributing.md](/docs/contributing.md) before working on the repository. + +DUE MAY 31 2024 23:59 EST ![THEMAZEphoto](/docs/gh_readme_assets/THEMAZEhahahahatestingargstuffifyouseethismessagemesayingyoudidhehehe2.png) diff --git a/TEST.md b/TEST.md deleted file mode 100644 index 2e79da4..0000000 --- a/TEST.md +++ /dev/null @@ -1,5 +0,0 @@ -I don't know what this file is - -hello there - -We honor the hero Surya who saved Brampton. diff --git a/docs/contributing.md b/docs/contributing.md index 343ebe2..97deb1a 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -2,18 +2,18 @@ - Follow a Git workflow of fork -> clone -> branch -> pr -> merge - If you're new to Git look [here](https://docs.github.com/en/get-started/quickstart/contributing-to-projects) -## general +## general - Keep file and folder names in `snake_case` (godot 4 standard) ## code -- Make sure your godot code follows the [GDQuest Style Guide](https://gdquest.gitbook.io/gdquests-guidelines/godot-gdscript-guidelines) +- Make sure your godot code follows the [GDQuest Style Guide](https://gdquest.gitbook.io/gdquests-guidelines/godot-gdscript-guidelines), use the [gdscript-toolkit-linter](https://github.com/Scony/godot-gdscript-toolkit) to automatically format your code. - Use [Static Typing](https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/static_typing.html) for variables and functions. - put scenes and their scripts in the same directory - Name scenes after the root node. -- Name scripts the same name as the node they attach to +- Name scripts the same name as the node they attach to - Label custom data structures with Class names for type hint support - Connect signals and groups through code, NOT through the GUI. -- Each Scene should do one thing, each function should do one thing +- Each Scene should do one thing, each function should do one thing - Make [static classes](https://godottutorials.com/courses/introduction-to-gdscript/godot-tutorials-gdscript-20/) when able. - If a custom class/node doesn't have a position on screen or is instanced then removed, then pass it into the script as a object instead of putting in in the scene tree. - ^ reach out to jayden if you need elaboration on this one \ No newline at end of file diff --git a/docs/file_exparimentation/ShowcaseExperience.txt b/docs/file_exparimentation/ShowcaseExperience.txt deleted file mode 100644 index 22aa2af..0000000 --- a/docs/file_exparimentation/ShowcaseExperience.txt +++ /dev/null @@ -1,58 +0,0 @@ - - -Legend: - General row reading format: - For storing data, they will begin with ">>" and then the code. Next rows will be "," or "]," seperated lists of elements - "%" means this is information in a line that will have the entire next line stored to a variable - Maze Bound: - R(id_number) - Room of id_number - Tile Bound: - W - Wall - C(id_number) - Circuit of id_number - S(of_what) - Sprite of of_what - Circuit Bound: - M((R(id_number)),(which_tile)) - Move to different id_number room at which_tile position - V(id_number) - Visual of id_number that plays until finished - ????###If, and, or statements? - ????Radnom function? - E - exit experience - Visual Bound: - T(what_text) - Text to be displayed - #Empty Room: - ],],],], - ],],],], - ],],],], - ],],],], - ],],],], - -%Experience Start -M(R1,[3,5]) -%Experience Name -Showcase Experience - ->>>Circuit Library ->>C1 -V1],M(R2,[3,5]) ->>C2 -V2],E - ->>>Visual Library ->>V1 -T("Remember you can") ->>V2 -T("You are in control") - - ->>>Room Library ->>R1 -],],],], -],],],], -],],W],], -],],],], -],],],], ->>R2 -],],C2],], -],],],], -W],W],W],W],S(W) -],],],], -],],],], diff --git a/icon.svg.import b/icon.svg.import index 8169617..591c365 100644 --- a/icon.svg.import +++ b/icon.svg.import @@ -2,7 +2,7 @@ importer="texture" type="CompressedTexture2D" -uid="uid://c8jkdt8jkuv01" +uid="uid://crcn77afl4vui" path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" metadata={ "vram_texture": false diff --git a/project.godot b/project.godot index c18f767..6882d39 100644 --- a/project.godot +++ b/project.godot @@ -10,48 +10,11 @@ config_version=5 [application] -config/name="The Maze" -run/main_scene="res://src/special_scenes/game_handler.tscn" +config/name="the-maze" config/features=PackedStringArray("4.2", "GL Compatibility") config/icon="res://icon.svg" -[input] - -ui_left={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194319,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"echo":false,"script":null) -] -} -ui_right={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194321,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null) -] -} -ui_up={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194320,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"echo":false,"script":null) -] -} -ui_down={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194322,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null) -] -} - [rendering] -textures/canvas_textures/default_texture_filter=0 renderer/rendering_method="gl_compatibility" renderer/rendering_method.mobile="gl_compatibility" diff --git a/src/resources/gitnoremove.md b/src/resources/gitnoremove.md deleted file mode 100644 index e69de29..0000000 diff --git a/src/special_scenes/game_handler.tscn b/src/special_scenes/game_handler.tscn deleted file mode 100644 index b0dad5a..0000000 --- a/src/special_scenes/game_handler.tscn +++ /dev/null @@ -1,68 +0,0 @@ -[gd_scene load_steps=8 format=3 uid="uid://detywurbm46yn"] - -[ext_resource type="Script" path="res://src/special_scripts/outside_maze.gd" id="1_538b0"] -[ext_resource type="Texture2D" uid="uid://d316msy0elqvi" path="res://assets/maze_assets_very_temp/OutsideCharacter.png" id="2_p76kx"] -[ext_resource type="Texture2D" uid="uid://d302b6tly3nlg" path="res://assets/maze_assets_very_temp/Apparatus.png" id="3_ish85"] -[ext_resource type="Script" path="res://src/special_scripts/inside_maze.gd" id="4_qdoyt"] -[ext_resource type="Texture2D" uid="uid://df17dmyxpjmrb" path="res://assets/maze_assets_very_temp/MazeCharacter.png" id="5_u6123"] - -[sub_resource type="RectangleShape2D" id="RectangleShape2D_bs24g"] - -[sub_resource type="RectangleShape2D" id="RectangleShape2D_5bthu"] - -[node name="GameHandler" type="Node2D"] - -[node name="OutsideMaze" type="Node2D" parent="."] -visible = false -script = ExtResource("1_538b0") - -[node name="ColorRect" type="ColorRect" parent="OutsideMaze"] -offset_right = 1156.0 -offset_bottom = 650.0 -color = Color(0.411765, 0.411765, 0.411765, 1) - -[node name="OutsideCharacter" type="CharacterBody2D" parent="OutsideMaze"] -position = Vector2(662, 157) - -[node name="Sprite2D" type="Sprite2D" parent="OutsideMaze/OutsideCharacter"] -scale = Vector2(2, 2) -texture = ExtResource("2_p76kx") - -[node name="CollisionShape2D" type="CollisionShape2D" parent="OutsideMaze/OutsideCharacter"] -shape = SubResource("RectangleShape2D_bs24g") - -[node name="RoomWalls" type="Node2D" parent="OutsideMaze"] - -[node name="Apparatus" type="Area2D" parent="OutsideMaze"] -position = Vector2(475, 288) - -[node name="CollisionShape2D" type="CollisionShape2D" parent="OutsideMaze/Apparatus"] -shape = SubResource("RectangleShape2D_5bthu") - -[node name="Sprite2D" type="Sprite2D" parent="OutsideMaze/Apparatus"] -position = Vector2(-13, 1) -scale = Vector2(2, 2) -texture = ExtResource("3_ish85") - -[node name="InsideMaze" type="Node2D" parent="."] -script = ExtResource("4_qdoyt") - -[node name="ColorRect" type="ColorRect" parent="InsideMaze"] -offset_right = 1147.0 -offset_bottom = 646.0 -color = Color(0, 0, 0, 1) - -[node name="Grid" type="Node2D" parent="InsideMaze"] -position = Vector2(450, 235) - -[node name="MazeCharacter" type="Node2D" parent="InsideMaze/Grid"] - -[node name="Sprite2D" type="Sprite2D" parent="InsideMaze/Grid/MazeCharacter"] -scale = Vector2(2, 2) -texture = ExtResource("5_u6123") - -[node name="WallCollection" type="Node2D" parent="InsideMaze/Grid"] - -[node name="Wall" type="Sprite2D" parent="InsideMaze/Grid/WallCollection"] - -[node name="Exit" type="Node2D" parent="InsideMaze/Grid"] diff --git a/src/special_scripts/inside_maze.gd b/src/special_scripts/inside_maze.gd deleted file mode 100644 index 14a97cf..0000000 --- a/src/special_scripts/inside_maze.gd +++ /dev/null @@ -1,178 +0,0 @@ -extends Node2D - - -@onready var player = $Grid/MazeCharacter -#it is slighty awful I didn't onready the important labels but HEY - - -var is_turn_timer_active: bool = false #I probably should have not had any "is" in my bools -var turn_timer_countdown: float = 8 - -var out_of_screen_position: Vector2 = Vector2(-42,-42) - -var distance_between_tile_centers: int = 50 -var grid_tile_width: int = 5 -var grid_tile_height: int = 5 -var center_of_top_left_tile_position: Vector2 -var center_of_bottom_right_tile_position: Vector2 - - - -var direction_dict = { - "up" : Vector2(0,-1), - "down" : Vector2(0,1), - "left" : Vector2(-1,0), - "right" : Vector2(1,0) -} - - - -var room_dictionary: Dictionary = { - -} - -func _ready() -> void: - do_grid_adjustments() - - -func refresh_the_board(): - player.position = Vector2(60,60) - if is_turn_timer_active: - $TurnTimer.start() - - -func do_grid_adjustments(): - distance_between_tile_centers = distance_between_tile_centers * $Grid.scale.y - center_of_top_left_tile_position = $Grid.global_position ##I need to move this just a bit I think - center_of_bottom_right_tile_position.x = center_of_top_left_tile_position.x + (grid_tile_width - 1) \ - * distance_between_tile_centers - center_of_bottom_right_tile_position.y = center_of_top_left_tile_position.y + (grid_tile_height- 1) \ - * distance_between_tile_centers - print(center_of_bottom_right_tile_position) - -func _physics_process(delta: float) -> void: - check_inputs() - - -func check_inputs() -> void: - if Input.is_action_just_pressed("ui_down"): - attempt_move(direction_dict["down"]) - if Input.is_action_just_pressed("ui_up"): - attempt_move(direction_dict["up"]) - if Input.is_action_just_pressed("ui_right"): - attempt_move(direction_dict["right"]) - if Input.is_action_just_pressed("ui_left"): - attempt_move(direction_dict["left"]) - - - - -##Add fail conditions and whatever - -func attempt_move(move_direction: Vector2): ## - ##Add stuff about communicating what's happening - ##Check if tile is occupied or something - var attempted_move_position = player.global_position + (move_direction * distance_between_tile_centers) - #add_text_to_step_log("Attempt to go " + str(direction_dict.find_key(move_direction))) - if is_position_in_grid(attempted_move_position): - player.global_position = attempted_move_position - #add_text_to_step_log("You went " + str(direction_dict.find_key(move_direction)) + "!") - end_turn() - else: - #Double check for secrets - flash_the_grid() - #add_text_to_step_log("Too far from center") - -func is_position_in_grid(given_position: Vector2) -> bool: ## - if given_position.x > center_of_bottom_right_tile_position.x: - return false - if given_position.x < center_of_top_left_tile_position.x: - return false - if given_position.y > center_of_bottom_right_tile_position.y: - return false - if given_position.y < center_of_top_left_tile_position.y: - return false - return true - - -func this_invalid_move_was_made(in_which_direction: Vector2): #yes this could/should be a signal - flash_the_grid() - var invalid_direction: Vector2 - invalid_direction = in_which_direction - if direction_dict["up"]: #I like match more but I keep getting errors - pass - if direction_dict["down"]: - pass - if direction_dict["left"]: - pass - if direction_dict["right"]: - pass - -func flash_the_grid(): -# var current_tween = create_tween() -# current_tween.tween_property($Grid, "position", $Grid.global_position + Vector2(3,0), 0.04) -# current_tween.tween_property($Grid, "position", $Grid.global_position - Vector2(3,0), 0.04) - pass - - -func end_turn(): - pass - - - - -func kill_player(): - refresh_the_board() - - -func get_random_outer_tile_direction() -> Vector2: - var enemy_travel_direction: Vector2 - var counter: int - var random_int = randi_range(0,3) ##There MUST be a better way to randomly get something from a dict but whatever - for direction_name in direction_dict: - if counter == random_int: - enemy_travel_direction = direction_dict[direction_name] - counter += 1 - return enemy_travel_direction - -func get_random_outer_tile_position() -> Vector2: - var which_outer_tile_position: Vector2 - var test_direction = get_random_outer_tile_direction() - which_outer_tile_position = get_outer_tile_position_on_opposing_edge(test_direction) - return which_outer_tile_position - -func get_outer_tile_position_on_opposing_edge(given_direction: Vector2) -> Vector2: - var tile_number:int = randi_range(1,grid_tile_width) - var which_outer_tile_position: Vector2 - if given_direction == direction_dict["up"] or given_direction == direction_dict["down"]: - which_outer_tile_position.x = center_of_top_left_tile_position.x + ((tile_number - 1) * distance_between_tile_centers) - if given_direction == direction_dict["up"]: #Below might need to be grid_tile_height - which_outer_tile_position.y = center_of_top_left_tile_position.y + ((grid_tile_width -1 ) * distance_between_tile_centers) - if given_direction == direction_dict["down"]: - which_outer_tile_position.y = center_of_top_left_tile_position.y - else: - which_outer_tile_position.y = center_of_top_left_tile_position.y + ((tile_number - 1) * distance_between_tile_centers) - if given_direction == direction_dict["left"]: - which_outer_tile_position.x = center_of_top_left_tile_position.x + ((grid_tile_height -1 ) * distance_between_tile_centers) - if given_direction == direction_dict["right"]: - which_outer_tile_position.x = center_of_top_left_tile_position.x - return which_outer_tile_position - - - - - -#Ok so like I'm thinking of a step by step system where each step that's attempted -#Is slowly revealed which I have the tech for but whatever that's too slow - -#Questions! -#func clear_step_log(): -# for written_label_step in step_log.get_children(): -# written_label_step.queue_free() -# -#func add_text_to_step_log(given_text: String): -# #oooh I can add colors or effects with RichText -# var new_label = Label.new() -# step_log.add_child(new_label) -# new_label.text = given_text - diff --git a/src/special_scripts/outside_maze.gd b/src/special_scripts/outside_maze.gd deleted file mode 100644 index 6d5a8e1..0000000 --- a/src/special_scripts/outside_maze.gd +++ /dev/null @@ -1,47 +0,0 @@ -extends Node2D - -var current_player_input_scheme: InputScheme = InputScheme.MOUSE_KEYBOARD ###THis can be compartimentalized -enum InputScheme { - MOUSE_KEYBOARD, - CONTROLLER -} -var movement_vector: Vector2 -var outside_character_speed: int = 200 - - -# Called when the node enters the scene tree for the first time. -func _ready() -> void: - pass # Replace with function body. - - -func _physics_process(delta: float) -> void: - check_for_new_player_inputs_to_move() - move_outside_character_by_movement_vector(movement_vector) - -func check_for_new_player_inputs_to_move(): - movement_vector = Vector2.ZERO -# if current_player_input_scheme == InputScheme.CONTROLLER: -# movement_vector = Vector2( -# Input.get_action_strength("controller_move_right") - Input.get_action_strength("controller_move_left"), -# Input.get_action_strength("controller_move_down") - Input.get_action_strength("controller_move_up") -# ).limit_length(1.0) -# var forced_aiming_vector = Vector2( -# Input.get_action_strength("controller_aim_right") - Input.get_action_strength("controller_aim_left"), -# Input.get_action_strength("controller_aim_down") - Input.get_action_strength("controller_aim_up") -# ).limit_length(1.0) - if current_player_input_scheme == InputScheme.MOUSE_KEYBOARD:#8d movement is possible... - #movement_vector = Input.get_vector() - if Input.is_action_pressed("ui_right"): - movement_vector.x = 1.0 - if Input.is_action_pressed("ui_left"): - movement_vector.x = -1.0 - if Input.is_action_pressed("ui_down"): - movement_vector.y = 1.0 - if Input.is_action_pressed("ui_up"): - movement_vector.y = -1.0 - movement_vector = movement_vector.normalized() - pass - -func move_outside_character_by_movement_vector(given_movement_vector: Vector2): - $OutsideCharacter.velocity = given_movement_vector * outside_character_speed - $OutsideCharacter.move_and_slide() diff --git a/src/static_scripts/gitnoremove.md b/src/static_scripts/gitnoremove.md deleted file mode 100644 index e69de29..0000000 diff --git a/src/testing/from_old_projects/super_menu.gd b/src/testing/from_old_projects/super_menu.gd deleted file mode 100644 index 20a0f9a..0000000 --- a/src/testing/from_old_projects/super_menu.gd +++ /dev/null @@ -1,42 +0,0 @@ -extends Node -class_name SuperMenu - -var current_ordered_button_position_array_index: int = 0: set = set_current_ordered_button_position_array_index -var ordered_button_position_array: Array[Vector2] -@onready var player = $"2DObjects/PlayerSprite" -@onready var tether = $"2DObjects/TetherPoint" - -var has_menu_been_set_up: bool = false - -func _ready() -> void: - pass - -func set_up_cursor_selection(): #This can't be at _ready() because UI doesn't set up yet - for node in $Control/MarginContainer/VSplitContainer.get_children(): - if node is Button: - ordered_button_position_array.append(node.global_position) - -func _physics_process(delta: float) -> void: - if !has_menu_been_set_up: - if Input.is_anything_pressed(): - set_up_cursor_selection() - has_menu_been_set_up = true - if Input.is_action_just_pressed("ui_down"): - if current_ordered_button_position_array_index == ordered_button_position_array.size() - 1: - current_ordered_button_position_array_index = 0 - else: - current_ordered_button_position_array_index += 1 - if Input.is_action_just_pressed("ui_up"): - if current_ordered_button_position_array_index == 0: - current_ordered_button_position_array_index = ordered_button_position_array.size() - 1 - else: - current_ordered_button_position_array_index -= 1 - if Input.is_action_just_pressed("ui_accept"): - for node in $Control/MarginContainer/VSplitContainer.get_children(): - if node is Button: - if node.global_position == ordered_button_position_array[current_ordered_button_position_array_index]: - node.emit_signal("pressed") #YYYYYYESSSS THIS WORKS - -func set_current_ordered_button_position_array_index(new_index: int): - current_ordered_button_position_array_index = new_index - tether.global_position.y = ordered_button_position_array[new_index].y diff --git a/src/testing/test_space.gd b/src/testing/test_space.gd deleted file mode 100644 index a686023..0000000 --- a/src/testing/test_space.gd +++ /dev/null @@ -1,117 +0,0 @@ -extends Node2D - - -# Called when the node enters the scene tree for the first time. -enum TextFileLineLookingFor { - CODES, - ROOMROW, - CIRCUITROW - } -var current_TextFileLineLookingFor: TextFileLineLookingFor = TextFileLineLookingFor.CODES - - -var room_dictionary: Dictionary = { - -} -var circuit_dictionary: Dictionary = { - -} -var file_writing_legend: Dictionary = { - "room_code" : ">>R", - "circuit_code" : ">>C" -} - -var first_letter_of_in_game_element_dictionary: Array = ["W", "C"] ###Hahaha not dicitonaries at the moment -var first_letter_of_in_game_effect_dictionary: Array = ["V", "E", "M"] - -func _ready() -> void: - read_experience_text_file("res://FileExperimentation/ShowcaseExperience.txt") - #Verify and raise errors - #transmit info - - -func read_experience_text_file(given_experience_text_file_path: String): - var file = FileAccess.open(given_experience_text_file_path, FileAccess.READ) - var current_callable_that_edits_stored_data: Callable ###Maybe I can use a callable instead of stored dictionary values? - var current_dictionary_key: String - var current_dictionary_contents: Array - var amount_of_lines_to_read_and_store: int = 0 - var content = file.get_as_text().split("\n") - file.close() - var total_lines_in_file: int = content.size() - var current_line: int = 1 - var line_read: bool = false - while current_line < total_lines_in_file: - var line: String = content[current_line - 1] - line_read = false - #print(line) - if current_TextFileLineLookingFor == TextFileLineLookingFor.CODES and !line_read: - if line.begins_with(file_writing_legend["room_code"]): - ###next5 lines should be roomrow codes - var what_room_code: String = line.substr(2,-1) - room_dictionary[what_room_code] = [] - current_dictionary_key = what_room_code - current_TextFileLineLookingFor = TextFileLineLookingFor.ROOMROW - amount_of_lines_to_read_and_store = 5 - line_read = true - pass - elif line.begins_with(file_writing_legend["circuit_code"]): - ###Next line should contain information on the circuit - var what_circuit_code: String = line.substr(2,-1) - circuit_dictionary[what_circuit_code] = [] - current_dictionary_key = what_circuit_code - current_TextFileLineLookingFor = TextFileLineLookingFor.CIRCUITROW - amount_of_lines_to_read_and_store = 1 - line_read = true - pass - else: - line_read = true - if current_TextFileLineLookingFor == TextFileLineLookingFor.ROOMROW and !line_read: - ####Read the roomrow and reduce the next lines until it's 0 and then go to CODES - var every_tile_in_row = line.split("],") - for tile in every_tile_in_row: - room_dictionary[current_dictionary_key].append(tile) - amount_of_lines_to_read_and_store -= 1 - if amount_of_lines_to_read_and_store == 0: - current_TextFileLineLookingFor = TextFileLineLookingFor.CODES - print(room_dictionary[current_dictionary_key]) - line_read = true - pass - if current_TextFileLineLookingFor == TextFileLineLookingFor.CIRCUITROW and !line_read: - ####Read the roomrow and reduce the next lines until it's 0 and then go to CODES - var every_effect_in_order = line.split("],") - for effect in every_effect_in_order: - circuit_dictionary[current_dictionary_key].append(effect) - amount_of_lines_to_read_and_store -= 1 - if amount_of_lines_to_read_and_store == 0: - current_TextFileLineLookingFor = TextFileLineLookingFor.CODES - print(circuit_dictionary[current_dictionary_key]) - line_read = true - pass - - if line_read: - current_line += 1 - -func are_dictionaries_valid() -> bool : - return true - -func verify_circuit_dictionary() -> bool : - for circuit in circuit_dictionary: - for effect in circuit: - var effect_first_letter = effect.substr(0,1) - if effect_first_letter not in first_letter_of_in_game_effect_dictionary: - return false - return true - - -func verify_room_dictionary() -> bool : - for room in room_dictionary: - var amount_of_rooms = 0 - - for tile in room: - var element_first_letter = tile.substr(0,1) - if element_first_letter not in first_letter_of_in_game_element_dictionary: - return false - if element_first_letter not in first_letter_of_in_game_effect_dictionary: - return false - return true diff --git a/src/testing/test_space.tscn b/src/testing/test_space.tscn deleted file mode 100644 index 18585f5..0000000 --- a/src/testing/test_space.tscn +++ /dev/null @@ -1,6 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://brvpbsqn7pngj"] - -[ext_resource type="Script" path="res://src/testing/test_space.gd" id="1_jqet7"] - -[node name="TestSpace" type="Node2D"] -script = ExtResource("1_jqet7") From dce74cbf26a06d9167e80e164de60dbc226842e0 Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Sat, 16 Mar 2024 15:28:40 -0400 Subject: [PATCH 02/86] tilemap data structure set up, make as seperate scene --- assets/monochrome-transparent_packed.png | Bin 0 -> 17497 bytes .../monochrome-transparent_packed.png.import | 34 + project.godot | 10 + src/main/main.tscn | 3264 +++++++++++++++++ src/player/player.gd | 19 + src/player/player.tscn | 24 + src/scene-tiles/chest/chest.gd | 14 + src/scene-tiles/chest/chest.tscn | 21 + 8 files changed, 3386 insertions(+) create mode 100644 assets/monochrome-transparent_packed.png create mode 100644 assets/monochrome-transparent_packed.png.import create mode 100644 src/main/main.tscn create mode 100644 src/player/player.gd create mode 100644 src/player/player.tscn create mode 100644 src/scene-tiles/chest/chest.gd create mode 100644 src/scene-tiles/chest/chest.tscn diff --git a/assets/monochrome-transparent_packed.png b/assets/monochrome-transparent_packed.png new file mode 100644 index 0000000000000000000000000000000000000000..4a99afc0a4b1737b34cb95c40736e1c9df11b3db GIT binary patch literal 17497 zcmV)mK%T#eP)#?{60QcRYpXf{RVQLKw%SQpC>70>JE;rV&AjMuGp)bf76b95~m zFg=~^bZxCpBomPD?|$d|&iDVE%h*$|rcu1{NiSLa-57s~Kd~S4lGt)B3mKfu$(W)v zjq1mme)#?e4nU*z%Cb*?a}Y0lHzesJny}_Ny~COt{4+VE5I(I2tAQ2M;4e!wqlfPYLF)$54a-F7#tX4SY6=5)l8RJa%m%(^`5D$`~aGwr&MipItv z@|nE*%7+hb_YL(u{(tb@fBR<{J!xGuzR(tGOSDdHVSbx{$mp@V9kKj2kB41jzdSf( ziJDxqdi4_^#;4-R2Wzgb%0=Inm({ygSp9>%mQbhf6^^(_1l>ea7_E4l&$3GA<%e*NoTuYZ!H;@SuI|LoxYgMklSCY$YF{gb?U;%FYzVz}+L z?4mwFg(LRTjbOqY$ZzYY?x@~Zc5rC_rRg_I>NterGy7*>ef4XtVUgDFR3T_(Bq3CZ z5)dAbH|~kPI^0Ra5|xJM9G!N2(TOFurr#{+V=SL!@o@EP)ol;=mF>TjU0hOUiE=W` z&32lnwIx|6mF)z@_Ekd@cvAr<}b~m;ssTfJJ zdnF+L)jz3hDe5bl*D%yzZqOC=t=Lo9GV{zUX93|dF}8FI4g1n+MONhHM;x)z3ca6x zcOGLa7WQuKb<$Fi<#ive3qokueUud1k!7ErFG9adH{&M zF4MYoU1>T$U8Z0~MMFh{(`9PtQz7hbOVnzp&8p1;#0vh(F3#vNeuZUja-U&VDJ(H- z?KT@tR2vispD3X(kCR@HkgER}^ZUJDfVd!D=;_Tz2>Ln^uF% zm z5QK+A7_3?+UE5`_;)`yg!p2`FS4NNCz@Am+>PRW`P?8rR=|?K_$uCC?Z+xa+>bh`V z3?_bzwFqG_t0wG-(a#AG;$NhYj{Pl7AzM;4=sY_%=IGOexy=yc`s8cz9~0~aSLV2g zCd}OWh&N6@U6werSx6zM0DyRKhJG0k7sHzJ5&a{R3u=kfA*uC=W=RuXyjIu?0bw<8 zWiI}Sb*K>K!_u$I$Hsn>G$!=Y`Ehg7|3MRV_WK_U*-SQCK?zBV)sSs>SCndMoD#g9I^_)Gc`VZ!>cbTLxa-+m&(8F`8lJHlr(} zC*xje#lEtNQoNx&^6ClV8oOqRYRDwnYzyv^Kyh*-_CylmvL$XAvjCz;<%Z4=q1F5~ zc=2Fa`l+;EW_IIubpG^{>8Hwv4?Ps4xD9t7;J?F&-%ZwW|*Jt&D_VklP#hvnDDDUm_f{E%5lM9-*uCZ>z z!J(CdhX$>NUH3Ag#C5Gxg_zZAayv#H9O4~7^zWp>{QoE0>|}ojUOYTx%d_QK4Pt4{ zJTvpNnP&tyO|HroyE~tZ5+FFqx#4Ln|-Y zY%P^~C+E6=uo`AX7rJOoj8Bx1bsbHV=?tGJlBnuHQGf10Wee0H**bCp%J%I!P_}Q^ zy~>u#mX2zVCs?q)pzYy`GC=(7OVYHCn9U|2$V~~CF_qoksJfhp-C;>#)4_{}hrInx zUG9L+UsPC8s*kMh&*(8&om$4;{FTmM+0ss0wB5eOuIM_*BspTcuUHknlJ${bha*Po zJ6y`jxI>_jc)aR7HeF#nSTY08urVe$uZq2P#{Hy;#dsleGIv zRz2qhqt!xoIAjUiS@|$Q{AMDA&L8GN1zvprLyo`dQBE_NrNP{R83SpNj2@FqAIa>7 zU#Rn|_ClDX?BdtHv?{7@vEq~D0uvR70`W#wUNH8zgdy(*FTxt#d)fkhg!?s4?osh| zmDZ&R>-^?`YA;q^$8f}!A2FOrE-!*1lXG3bM5?FHGyA7L*f{BkWz>tasm zL?^NK+{gd$=jT2?_c6a}Sg1*ESQpU0pH0RWVXae*E|{6TEju)~s?aAxXd>J*mrlY_ zXRN>~g+Bjnn0=nKdMX6}t$z+GlJP}E|2XYSL>IIo@(HAx+)op%HwKH2TOo)LIXR(4 zS(zagAR`pr_k|_;{SV)deV+`wRERSom?A3v&3}c6(n@-)f8>Z2_0g?Vvn{NXnV4z% z&FMF@ZcaBagA|35BuZf)qb!|On(Vy>g3!d=HICT#KYY$1COQI~ioKxXFaO41o&6Qr zic4u~yYkz#;o0$z z&sD`&yIJ_*q3=BpN#%e412>+R_Fqc7L+>4hw;r+FmE()of{Oj?5WtetI&Zras*bleYGP!eLbN8Hfp|bt8PG5# znD`H`E_*=ng~x4u^|B*YKK$}|n#eAFMAAt*0kQn5BPx?E@y2rp+VTxn(tugD#C3ml z0#TCmm?^X-f|#h!f18@9zhztReYjUvFi|gGeCdm#zVeYmXVsuSQdp*EdJ3pztxhW@ zN?BUu&m$dI-BC5@jgu4F#W1%Tf3P#Nd;MqgZ?Le+?$3XlVz*e`WHZ>m|93pT=zHnQ zqM?^B2FykMW?B~MOly!0g5A#Hx#5BsVpp4O{Sy*zKP&M`CudoM9a6~AJNpz<)OEr0 z2g%o`mxk8;^*@tpooD~@Zz@~n-dJ+0D&o>s4HorPMNBk_CT3tZCWO{GJSXH}xQ!x; zpuBNVQI{TBM(c+l!ul?Wr65vN++H_y>97AX-RHdcZ~p7N?XVS9eN}znVbvom=~W7T z2n0)Sdad>5G$uubriJ4~@rCTuhZd2JB7+plh(dvU9)|*XcB0aJ&a;RwxaU_04=}Au zTi_%Gnkt~`~_eZi9FNhM@WX<&lybRWD$9DGnb!6FV>zSACvp$b9AbBZG z%aUq0B!?t*IMJA&})`P4FvxMk7kqHpEPCaYl5EM*44MDlA?yL)c zfeF$&3kv}R!DWkCH_Kv$ESp=4;il1P#~ECy^Av}#Wh^~B0YXevJ)fxhyk{VmZXt-j z*a&A+AHkZKK`Lih0P=%4vHeJ z^$c1^<%N)_0EY-ngfK_wKVRURCx5ZAsIQ__L>FRx7`Ux~#VG2Vab5^5%#@uWUa>^8 zwlGRPUKJ2x>D99~4$(FdV$UG659r)oa#vbK=}TXT=)%gCgq7P0d`>%_J23rbQ6KQ_ z49QbVh^SC#qEvQ^rB_e)1PI$x6Sb7F2O;^J-?>b}^%tw$67_SL^^?>hS!8lS2wVi< zN@^X7F90!l>D62_c^U$LL;t7%Vn35^iyYJB^bk4BI^u2) z(@`#nlJj$KJY&g(jsh=Ey^afue3XR;lj9Izw?B<1I&C&E+G;?N0Zbz8M?UI5{R7xG4v}+!*$rF{Db_}8DgqhK+#IqDB_y-< zCAZ245Rq#_tUj19`m|1i)g0iE8`f-Cv-*i5V}gPS%14c<`KS~X0cH+o1OSoKjHrQE zZ+K3ME?!Sm5HUYyT0ln-kaR_rr^N_eycp~y9-YO(-v>UA=w;|YpM5ERSl?Tp{` zjPtPBxVXqk(V{4%gu9dNBQ-dXOKzt=tap9*DR^eHl@HV82NSOs)E2CNQcDn--N;+0 z`6yE5iX@b|-N`g(7lpNylg%BF6`{sOk%|^YJ%v#Ui_AY=+MH`Bt#O+0B{%KH6M(Q6;DvRdw89bhj{1z+E=MoaJ5f<{3KAtCplwt6C=Q{h>w>wrFwA|`#iEGI zM3-+tJXct#>fyiAkTzHgkXz>%zZ415jvxGC5H~qEL29<)fa0NU9qF zflpK|U@wHVfW2@;g}s>gN;=n*mAN|Db5!OZA+EAE zeq)>O7bP~|rutPPs}}l#R0m&rX%S9UR8T>zbPI^Lx*OZyxa0Ax|A^NwtgMvmg`K^} z%vwLKeizR^CRmKwEis8ihL#>h#|fKm^L_ZVuor-EBq6+UpBbwLk&gf+tzEuosvpKu7|DiR38R zE zxXq}cFs9PFouN&_L%=n5o2|_ofAs#DMQp*kq|mNkwf-vj9+#`H*a>#j5t|>Y?pXFULCn0xA?{?= zPKJ;OLM8}IUq)0wAlyR1cH!lB9?$AUHAci1WHmzjIRv*KR!J)vuzV>ibsVYZK|WEo zry#ampsdsvlq#hQ8floBU^hh@p=_qr zQoIp!9A9vk3$4uzp|#mItP!hQRPECu5>@)NQBVe1njQluq!87k@^c3c4rLb?7E&5g zL3EK#gDeIYS_37(ih26L5i2ur-;fsFL%#IxD>7EVLUEJegI+%0n0%sdTaQ$aaKklD_%O0aQ5w(F+B#`M$`~OqeLr_M1dE3PGr) z#M&&6M^+ZEwHmZe6nKOpM}(15AjKSlG9m;)_QE#)0xw*q6uU9Rx&SYP@1&1#Q^}Jv zM1ettP|!0pt_H0Wy!_|bi-{2IPyGV$So}xX3!5##tM!;DVG~3|Dqh*eu)`Ahu#2Xh zSakeEsuwDmJxIND8{XXT@j0-xq>j33tmRQnC@lmz z8;c=MRUyz4BdSyU(>Ojz6m)(R9l1_`ra8b$ImC_~ju@q+aqE?#h%2oFntPgI0p=@47MOA44NZ$gP7a-w=^6wq+eyO5orGBqDF z&d-i^)CwvTdC4tY%{7aU85_Vix>~1L(Of20( zTGh%TQn%EN8U`P=QVo@<&!AYn?19Tp6J_gN)w}ShA~&q@>%bF5eshB&gBPkySuPXd zRKZM#7p|ZOD!RkEY?L)-|{2NkF<^mDumD?DAZ7`h5B{~BBN(kFA5B;BXf=df>d`XjirUO zA=$)7v1~9zR0x&bNeG3yh}`zASGQgTC7?nGZAl$8lqmH=$d_(GMrtROtJZx)C1{qx zSDTq?7+SpjTGzCjD#VQQLTGJD9ww@;!LM_~&_ngwFJJp5BuWTvbq7|0Ch5}7IRElR zB#RCXEjrOUa&TyNXm)5On--c8GT00TdXwFldmLSm80ymNRr0{*4FsWogodBPl&-_N z5JGErqyJA;ib$a@xkW{i!6mm^Dl1BDlx?*MixIH)(mOmoTx3-X4cuN}T_`dX$Xf)# zY$zaMqCP&S3N0SN=fnAI@3ph8NooB5=G!el2YKeIZ>p$KVC zN=G%fSooRP4vL($sh1Z{z8dib6UioI#seupP-r5>r8Xz-7g?U<(8M%kSEQSoL1|!I zq98cpGC>3#EJewOpQ?eSUk3=tog3wUs%DaF-@@ADyUJ0yi^RvB94<|-+$-0x%bFfd zR9zR_6VzYppfX+=lrOihXM!NctZ&Ta8&;b~!s4~p;-#P)O4NES*#V4`S3 zcJ?=X(wPqkl?o^d^vhwQ6d9MNF6^G%0h5W84J9w?2Ad*>Z_kaaj%I`wgqDTo(vUo4 zE7nP!Qa-h6CMRkSwZD$DTU=VrNq~x+X2EVn#^o{A-LaeN^QwERd$)8E#FeV(`si$i zk;|%>&L+EMkIo}k%e>y2*`3*479uJvF~|`viwROGp*uf6wsu`k*2oTO#Qh`wT(opvqE)Pls z%P~>-Hz*LgeAE&#Q6Q<0y>Uk$)kmi}-*S3mx^A1VBvcSuK)K**etBf35Nq)4D1ms< zpG3WXCvCR38aC!VMFq*wI7A=0sbtVB5q*rxd*o%zaL#ZR9+$h!J|Fv###`*|WEdb~ z4b|bK(&0&-)P=X>#}mfutHVSv7u$w#k~)Y)q=Z8A(gwe`@d&-yd!-3|95$ z!B{eX_rH?8i0FCBPpk_+(nn11SN}%+`}sE}(xRGD(z2dey+}){Lle;)OXiKoEu_oz z_rGBX6Gi$@K#0}^@dY0ZT6l3>UJOx!=HH@xBUSJs=qVxq`jk!NR2>z`Z&jIl<3t5o z*d{>ObOeym^ZvJc4me`l4cj44adCOd#Bd1QfF`^;rthaM9adIJqZ*%bi)D~~Kw$vW z45-RHtCmPGoKzu#aYrH;gLca3*?N`w%z1BwfKa1aK&*ZwE0jEKbBttm)2y|?df-!z z8hh9Vc8B$7dQ=^Sc!kZU#(x3PoS2m#q@5sDgErgNs|xiJ=xG2#Tt1^mK>X~>={Lz; zi+d^EyE?)nix@uT`xyfiTYM> zfIv6`>a+&8eP=&1`T>udGUC*)ipV0$Kd)+Hw0)pPs%4FnAm*RO;+hB%Fgvxu1Ryfw zW)Ikn%R`}4D*%1>{cjIbW3iHd$bVo@Fs|`W_meF7HGb)dJWAH$Q+9@3Qzwc;EXYf>u(2~d@gM?v!_9CwyUW+BZSEknLj%93FXc>Ezy81*FL)5=vD-d_n z_o56tid?))wRL1x0un{_#V`UHk$m6~lkCNc6+Ebny%Ik-#G-Fe{`4dE4z(4+PFRx) zUNl&0om_!HEeHs|4!l5+B}%)(UI1dUz3}kxL5kQJ^|Fi`q3zsGC`pJ(YVfDF7ZLqW zZeM=*emwA+IFjl*A|~qX@MM#O06Dn>18P4NUp)Jw%wo(jDXKuUhk@c1s@Vd<@nll( z8C{lo+pHp8L`+Pjh$aUWQF5dyqx0)uGjUOMK#~-h;#7uW6qJb~HzicosSxOk;^lN^ zwDKga7;2u*is_%>la9kSQvYG=$orLko#@*K1f0%ACjx25o5FwDV39`(j(e_Ys8MNWGF03ZNKL_t(|o+-46qK8BL{1<**bI$Hf%{hKu zecn5dq3ANAfDlg4T87KJ?Wp{U&|V)w&oAhp%)d_^MDwQ>nruNk(fdhex7JGG+@1q1 z-vZ);D=CQ95$Z{0+*I+h9xhKij3U_Cq6s5Yh5tj^f*gb{sf+R9jqf5Av@+pE@YbHT zHvNXlrSX09JJwRUV@HaLrcYD|Y_(J&a6yqrqiU|bEuVIsxM!Y0{9!dnibj$6@W$Wy z)T>?Jtvju-ruG?Iraw+Usj+eh@M4^b67Zt@C?IB@5xh`%F%$NJV5yeekx1+E#znQ8 z)Llpy&I@HxzaJw_wLh?zI-)wmP3=z4^ayFG9)j3&0K5RR1w<32=lzw``yUl?2Ovaz zvF?t!$8N@E4w1QBbfR)_#)TQ|A|+Af!;E`=DD3lzq76~yeZpQG9I6^b!z=0|1 zkk{rLa9#Qk39WN{U8oRZ>5&TI>H%&FAST)ibY7z=Q4CGoPh~wU3;)yEACf-oUm^w4 zI>LD|zPh16gauU9pu$SCQ}$wf=LH`uhGK|wQb*L}7pcKN)L#4uW&TsY+RrgHmPn=S zya^0-`v?}Fh}@u1P|zLkj3SMz+Q4AQ&w^oPlFAq3w@pb+G%<@KhMn(+kT`@cB9mD% zkvfDe!Jv|8)Xdio3{*7>A`(&jyyS}k6)CtC)-X{{AZD4ytp+#w*~qj}YzhclOiQd! zr@dtFe=AZ*R)hFSS;H=k;-#cxEo)Lh67uQ!ZE0OPzi4hEp|#n3#->r~t;|xTsx{G? z0EAzMk^=WdVuolikr4$IVlv@#i(&EUyUIgBDik+{+lU6_aF^VA3ZjlwUk&Y2Y0lYo z4-m~VAabJt8HEuJ(Pr%>i0;Z3SOaJ$rxrVjy|nlo=PkZMB^X*k5FJFrwqv`G?Y=_Z zZUWg}8dn%Y%bb|ILX+@mn zrJS?3&T+oL9}F*NP5w@Xv<&S-IH1TYuPdF@H6(vNipspvXUu1;4G^H>=Nmx9i~(h_ zh5{}?Z2Dk1We8!WP+X+_Nh$=jrg$%U>!zJ-jVPhFyMr8}l@@Y+-n*aG_t)p`%xn5B zwJrdnsH3`1h4|nCAZ8EvbvXk%4)N}1EB5$|8QqNS?B6~QgBJu!HkWLl_cCp{Pd~mo ztSE2#108&HzxqI^bMOKal}}NJ-fsy&fLA}NsSKFW z4yQuY6bO**^GdWc47wUkXmz+V+(PRC^$<$*!<2Qdyxu7j6&??G0p_({5$qsp`qd4Z8uFIS*H-?Z_P;6>{Qc(8cwl3Okl-Y%2Tn&y;-kp_@>=pvSu z5Lo;qp#?+K{6#CE7(078hZSQoStG4aY-^mIv~pKq!u2qq8t6wErkzEOrm(~wSaM$qdBapK z=3Qg7Oph4dPAxX7h}6U+h{ks5>colKKCeCxiV+ahi*k$Fo#aO9kV(;i)YP84lq)zZQz1=cQ7muWoP48qoXd_8YjnQ2-IPJI!G2U`0a|kjOl$FUY z-m_;igd!K7&OiDd$<(_~_KpTW!$j@6r>Cv|D^K9;7*8|h5d1q5I}_^@HEvcnZ#y8w zMDfcnrBuHxCTi%7JBplLeBi*gV{hC+djlxIM3K5{+eRz830xXQaeCK1N}k#mT?b?H zDITpHOhPbrYTkDIEjA1$mH9-7_C{|!r+LpFlWWll+WSG?`PQp|m|wW?s6W&!AeLGU z({Jv&N0mFfJ5mnmuh4g`dQVK0J6uP}8f>X2lSCGM(nK}3&!+tz*dqvDfZd=#KzQRz z+WZPZM4J+pQ3(95dsM74*#ih9^>jMUs`osePEVFca$1Y0-!%FxQKuIEykIq0E`-*2 z=%Fh+t9H+xZO7UhQxgSo&S$Nq+jZU}O;48d9+&1ETE`}{d-E*{>f7w@mDgFRr_fX= zIa_EWdHP8eLI^AbmqWB}H<*h}!Nh?BCRcl-2mnM7V5LZ!)}t)S#$!tzyJidB8m4_ zIl%5%5`w$ahNpH_n3$>tg(Esi4gLv~`5*rJ!^-Q29ukT^(tZuRU^>(=SZA_cOggm2 z$TL&g!;{L?0%BrI0An510dq&SDD);b(IvZ&{`G%k*!=b}gG4b>BW+Ad2pdjajNuBC zVCUh)hBY;EO#w@Gv*;tD-et5F)bLj6a1C`x`;5Gak@Lb%8EV09O5C9i+?MakreZ?p z`-x7b8Nb`KE^{0AtJ^xLReU3fKy8+4_|s3$q)p#i)WBVikR!TfDXPn;V~RvJ*0_+Z zfBN4D!fn?)EH;tG?SHR27}AVS6!z{Qo2mU86SZ;lEn{sK`o~3HZT45`Crj!G!t+Yl z8$+oM>Ow%|4mh>6gB>|w?dQKG*FRuhvC5U**{MI)SskP;?j;w>=`EohgYJfU`a1;` zADTrbeQfN9?-yQPyO_#p2AqfDj(KC)G0AgK5mY*6^}hct?Z))@bsp-E;SlQr#U@H% zW4CflKfJNdm%Xu03QfPMH7vQMwW<(re+TpHjgO7}?i+JJRtjp2b%lj2;u-YZOeH6U zGGF~jjW5U>1d|L|;Du1xqEdt&+3aH3N{yh$GpQ<$iQ3Q(UH~Ey)JI-9YjVNslfsU8 z3PSa1u|sHi=kg<+N0JcDS&*nk_!;ehKr5R>H6__v)Hm&m%se+yQPY3-G>8_| zl=x_yCYxO+MJG-a>fE40#1{ksIgnR?ig)`v>vnzyh#AG0D9QweU;4r_qHnLEZ*3e6 ze5z9M!}oJ zG5sb%gpgc8_J7yq8n$s0mL6_LK%korNhdljgK4Nn@$AyW!1AM|w=J?QvS|cVynFlY z+w(s|Qpjeb6asI-H@OasP=l28vHS;{0~&->?a0k9bxU) zFkIPtuI#;mA(UY8UA}1~gw|2@#kUtE?Zrfh=WQ=ZWv!^t^D(ah6`S^S`{ljgi6DTn zk~-d~J0U2bD1+N*)zm!S24d?O9lSD-s#j1r*?w*Plb!vvx@CPt>q2$8G<`3u-4It|i%N`_U9x6QvfvF;m?|+ph z2`(o(Jk^1NCbF{D7_tI6PU;EXd%Hd_tqXng3$oQNgZ*_I>q;*Dj6MOej^X?a0WmfP z2%TT_G1IP}h}VPtV@~bd8~n7N`zx<+zD^JaFKk$|>rS&7TYvXb?>{`y{ND0+aOGg11hm?)~Z=vpc|>*_hg`?iug?32_-wq6xfVCjL~ zuH-sMQ32Hr?M%F2Q?Q$|_J&$IJkQB?-RUf88cpkJXjpV&K{ocP8psvf4~R?Z(({Zj zHBnmfv_Eu9O%b2Yo}<=}eFYBt)D7^fn+ z1XT!})HHGFsSvdEHqqr39kLsW?(N%(OlJu005621m`DYNC6S^+47HI4nhG`U=O~bQ zBN#|b%)O1FkD$2$I!f$j6ueL&G%0pRo;i(TDmD0HUH_>r{v2igQ@@fWb;yDm(WsfI zg_q%6(&}c!n@iB8qMra=DWaa?*DXH+=SFm;sm)4HkN@lc=O>Y&dmp636B7R*MX+ra zxtRk1-UIgw1CE8;{>s@`&Z4<=4z=-%$r6b!+T5>udhqrJ*fD$+>OzH(tqAj-TB~6O zAkI%aj#T6{>K~tW+^NOUO_0iI$7$Csw-;*nZ7OS^4vOBhAzU0_SN6sjq3YDF_RzF4-;H4d?# zZQQ^vO{}!3)((HtI)%N!Z!Nj?>emXLMoMn~1PG!6+iB2TT<`^Qu9$!57{({6sLyK1 zVQVh1W)V}%iduJ?umOhKi@mpliTA&K|63dkz+L8v6O~Oa^712!{8CMQ-rn0Ne$L-V z_h(hvy&n^GDPRtmaX!!Mr@)gBKW)p$<=gV%?89E{z5V{T!32JP<@MKoiR+0srvjat zm_ck&!B>j2OE1$7DnB3~w1O8?LkN4Z_x6XMVn;F{5L-M0(bz5$^YA_9pDwE-%N7z7 zLPzCsdolGy;dlb80TcwxZTXleT>L4CvP2u(6?qvQU{*rWDh{G~`J#a#VOl;6iK3;q zXKHo}PaMZlVK)QV%^?;mi^tiG9_A+Uy2~k?s_R^IVqx7&R8TYU&R{_7$GW&Qwa^L( z+8*z5+fzcDf*_&I9kAI@JbdLA+_ZHcmE0{MI&`KDYf$foM8RH6z4X-nKpYG`#nM~- z2+2pp)6;M6{chbyNLbN{qESHwBnnhatw4mmc%cFj>JPpgoz8YctP9LCc!8fnM@_8; z)kxw6YVc2_%zt7Cly8>H65lt~!498p&Y>(OuUG88BJ2fh_vAe#ynM^&o;@OWI^GnY z{BIKn8CHaY)G$X$H|3&UbIpmMY3gT?&R#cve^U#C~8TCsBNJ9G@1$eU~RnzZ7@u@uW@~RtHh) zX9p9gpJ>8HUuzhx8qGNlI5n}>5gfjqq5`G|7ee;4btJ1czc!1ug}l0DzOMAkSI$C| zq31T=$A#a<_zr`D{<)EZiNZpxk`zQ!Gg~sKGv?qPPjiHSkVk>Ff{iC3QR`-RC z8#nF&#PDDJ_tq2@LN~pB$~%~CqNEr1WI@H2r8sqP5=7>(H@x63Qd}Z_#)jSoo?j#3 z#YPW4hYppBab5@rMSeN%jV(Tp<8Yz5#Ic4?O_Zg-l@%89&FrB)EXi)9w-Ni+Cm%kYnJ+Tuoq8l-Ab-*>RL_q zos-lha>v_fp1btG0Xja1>+p{c2puJi$?hxgKvGns6bO$rgpOj%9soi;fcg3M0B-za-#Yfdo=KY7Z_ZTZYIZTanu z)DFjY&lpt*Fq&K*YPb|skl1n7FT7l)#VFC1jgJLK#otiB+f8`)JVPBv>e3s<_Hu8$ zqq?(`;%;7p&Y{NiCu&-&X>=9D?LGWImESl-adwHefJTY7mmc!69$FllHmwWKcz)UL}C&>+B5_xozH>r>)v_%R>;YuPl~hWT%KyI>~GzH z(kh=Q4`_IKEe=v2pC|>L)|=K`>&T*1{Dzw#YIAjmGHMmGgp``;o zSmvfRmjV;0V7%*AEIl8Vym8@WXU$Z@!M8PwrRQ;h3b>;NyT||^AA;t&BS5J3g?V4+hUEkBqjgB2}VNI&?f4Ty0nrm`2= z9s$9`r4c;_Ok%4OGeu4sRVqSKmdjL8>NAqIC3ZLGY*?en%{c_fAxgfO+Flrr)1Ekj z&_{U^JYt~@M>2ZNE;XLY*iSWvMbi2bYw5F}0>Ox&(wtoK)%(d=VY`de=A=bfDT| zMFt;M|MDqzYaz5R)lF?L+&&c|#b}k?W^OMy74Se5x$2^rs7XSLW|S9FQPm|xlzZx~ z)Ssb!?QL9WL50Fom7qdQ)WoG1OqizR1%{nJCnHFYO(aFqT}LA4^#kR;|3(& z!18Bx)Qc2|iTz#$0xGbwg}orl_eWKO|J(G_3d0KTCuJ`VJ=}jubQeh>A0CVG`zGoI zI}y=O%iRM6ernZAK;ZwA5Zd2kFZ|M(sUgsD$DJHnVrF44(1R-e6)t5%y+nbZ{567@+Fq~_ z8Y?G`Bt(GDZ*~KM+U5^$TK%}D(i}iG080-L8yn~mKD3B@&WTh!&t9O&uI@_b8-9iI zaGA(k&u;?+Wol!x&)o7F%o-<1wHmuTskwF88t;S zy8&Sd;pixWSPlqIg;TNd!Pak zf)|)5P~nIfeJ_TWmJiRZm}-ne zOk%f*vztS#$0bJAkFFoVF(b&}q$J8}(D_AZ{~`!%fJ!+x*slnorOyENUlN44%O(W$ zvPf`=iE5&(8X&}KdC^2AA(Bha#Kh7QZX1V4Wj;1;fY1W!&_l#|ejN^JOSa*^K!KpX z|3U>K(kxJeYJ3q)079H0n$h!*Nwd7jB>k`2Py2_xs09lO8;yoD&sYtjAP8xgP~yi# zgk;I^;XfV28^esPSGdAw_xxn9I>N?CQhFmb1i*kX9tm{a@O zFAqJ0?3n0@a@fC_L1NgJFS5;QCg-{FMc8pfh-~uBk9I=t0Afo`eTJy>!L;Kjv|)=7 z%D6b~+waCXs0M3&-W*I6)$v|nFPO9aX?u}^IGN6@F(rW}7pHc?UHDPu!?SvG2UgMi zWDFU6yRQ@hf*yb{wY`u+P2Y_x5bpE~2&(+jsZ!){I=@y%!0uPh(%FEf9XpU=wi;H= z(|>IlGFlrNxPp07)Hk)gcnX3Ek5-&P&mwR*?=4T@#0wlo4JlS3f@7m)Zu_o#>%fbT zUSu!yk)~1Js4K#-h=35!-IKzAXkXPSHYf|BMY{`~Kxih2O9zKG-{-l*EYeX^#ut`o zQ$L4@a7`5z5d7>~+89X?%dfqAE~5wX?Y7ruQHPNhgW<2mtXhC9-BQ`oG@9RrqZ3GdZ63Q1F&KxKa=ge|a0P;XGC>6( zL|YPX*y=w1m*^ zgI-Oiw%9t8PMXpAA&2}>3zkt=abvgHU}2NkT`zR)I0UT4``>Q7 zU=Ebjy>YLm3`g6}z47j6tG|{#$lxc}Mbt(IA?YaFX2Gvc5ZcVZY&_s*qR{rjpH$DM zCJ1QS6)Rr*W!b*6eVaa5vkAv0SPk!fR=Yx8flZiVb@Qz#;fYHR8*S)d6uMs=!Z~T_ zbx%6=0r&$4{D)4>T&c{w000BoNkl=kmmhs5+I6cjQ7)MMD}KKkTz7AKyleWH~&-NEv&v zLcMW*@LCw`21M$a9w}uGRfuh9)ERC^)1u8LK5_pGFPmIxUFj!tZxR(n%ucpK^x0uR z``|9HCv{GjN(DDQT!u`b$AyEPWO@pZ77umkV5PFsG+NXrKH>Z?yqs>$?9S+^Xhu_C z$VLjB8mWfo597@P82Z1T|AHLJlk}we}$3!t*dEt z!7%^4>xiYFEFaGB8La6ii;C%nS9aOH!bW#*TtH+OV{a57$dP;iH3*1l$K7_o(4kaa zi`S;n9P@ z%i?Swv{dHuhu}2l%s=hDmhKb~OKx>`N+FyhmDaQHaz+>KvuSwQgYr@7^0I;1qy?xi zYBZy#Y4qLCX7*W z@bZGY^M^$@O6~wY=b!%hFPx3CvI7u1Iy;v=07Th789n|A9_H0F3Yg5UR#NUc&2;gl zGtLVLlPjm$z}YKJ&~oc)}kZb# z=n*0a%lOm9Kcyp5c<_xrRIq#T+6T4O*h=-{4bp oOo>nMG&O#re%gsGSP}jI00~S$<(_&DQ~&?~07*qoM6N<$f void: + add_to_group('player') + +func _ready() -> void: + pass + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + pass + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed("ui_up") diff --git a/src/player/player.tscn b/src/player/player.tscn new file mode 100644 index 0000000..a3e2cd4 --- /dev/null +++ b/src/player/player.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=4 format=3 uid="uid://bp6oyjqvoyffq"] + +[ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_bwexj"] +[ext_resource type="Script" path="res://src/player/player.gd" id="1_fqi5k"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_v5s8d"] +size = Vector2(16, 16) + +[node name="player" type="Area2D"] +script = ExtResource("1_fqi5k") + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_bwexj") +centered = false +region_enabled = true +region_rect = Rect2(432, 0, 16, 16) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(8, 8) +shape = SubResource("RectangleShape2D_v5s8d") + +[node name="RayCast2D" type="RayCast2D" parent="."] +position = Vector2(8, 8) +target_position = Vector2(0, 16) diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd new file mode 100644 index 0000000..94cffdd --- /dev/null +++ b/src/scene-tiles/chest/chest.gd @@ -0,0 +1,14 @@ +extends Area2D + + +func _init() -> void: + add_to_group('interact') + add_to_group('chest') + +func _ready() -> void: + pass + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + pass diff --git a/src/scene-tiles/chest/chest.tscn b/src/scene-tiles/chest/chest.tscn new file mode 100644 index 0000000..67fb56a --- /dev/null +++ b/src/scene-tiles/chest/chest.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=4 format=3 uid="uid://cojb8qcua33fo"] + +[ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_dpxiw"] +[ext_resource type="Script" path="res://src/scene-tiles/chest/chest.gd" id="1_j2k5u"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_vdfc5"] +size = Vector2(16, 16) + +[node name="chest" type="Area2D"] +script = ExtResource("1_j2k5u") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(8, 8) +shape = SubResource("RectangleShape2D_vdfc5") + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_dpxiw") +centered = false +hframes = 2 +region_enabled = true +region_rect = Rect2(128, 96, 32, 16) From fb61ad1a21e9f26693afbffda51219808de24011 Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Sat, 16 Mar 2024 17:03:28 -0400 Subject: [PATCH 03/86] process based movement system --- src/player/player.gd | 41 ++++++++++++++++++++++++++++++++++------- src/player/player.tscn | 1 - 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/player/player.gd b/src/player/player.gd index 121aa2b..2b2128d 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -1,19 +1,46 @@ extends Area2D -var dir:= Vector2.ZERO +@onready var raycast := $RayCast2D + +var input_dir:= Vector2.ZERO const TILE_SIZE:= 16 func _init() -> void: add_to_group('player') -func _ready() -> void: - pass +#func get_player_input() -> Vector2: + ## make vector representing player input + #var dir := Vector2.ZERO + ##dir.x = Input.get_axis("ui_left","ui_right") + ##dir.y = Input.get_axis("ui_up","ui_down") + #if Input.is_action_just_pressed("ui_up"): + #dir.y += -1 + #if Input.is_action_just_pressed("ui_down"): + #dir.y += 1 + #if Input.is_action_just_pressed("ui_left"): + #dir.x += -1 + #if Input.is_action_just_pressed("ui_right"): + #dir.x += 1 + ## prioritizes left/right movement to up/down movement in diagonal inputs. + #if dir.x != 0 and dir.y != 0: + #dir.y = 0 + #return dir +#func _process(delta: float) -> void: + ##check what group the next tile is in based on your raycast + #input_dir = get_player_input() + #if input_dir == Vector2.ZERO: + #return + #raycast.target_position = input_dir * TILE_SIZE + ## should make some sort of tileItem class + #var next_tile :Object = raycast.get_collider() + #if next_tile == null: + #return + #print(next_tile) + #position += input_dir * TILE_SIZE -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: - pass func _unhandled_input(event: InputEvent) -> void: - if event.is_action_pressed("ui_up") + if event.is_action_pressed("ui_up"): + print('up') \ No newline at end of file diff --git a/src/player/player.tscn b/src/player/player.tscn index a3e2cd4..d916dbf 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -21,4 +21,3 @@ shape = SubResource("RectangleShape2D_v5s8d") [node name="RayCast2D" type="RayCast2D" parent="."] position = Vector2(8, 8) -target_position = Vector2(0, 16) From 0b73a6d89ed5028193f40ef843f675e09317fa31 Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Sat, 16 Mar 2024 17:19:02 -0400 Subject: [PATCH 04/86] next tile checking tile based movement --- src/player/player.gd | 57 +++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/src/player/player.gd b/src/player/player.gd index 2b2128d..e56dd66 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -9,38 +9,31 @@ const TILE_SIZE:= 16 func _init() -> void: add_to_group('player') -#func get_player_input() -> Vector2: - ## make vector representing player input - #var dir := Vector2.ZERO - ##dir.x = Input.get_axis("ui_left","ui_right") - ##dir.y = Input.get_axis("ui_up","ui_down") - #if Input.is_action_just_pressed("ui_up"): - #dir.y += -1 - #if Input.is_action_just_pressed("ui_down"): - #dir.y += 1 - #if Input.is_action_just_pressed("ui_left"): - #dir.x += -1 - #if Input.is_action_just_pressed("ui_right"): - #dir.x += 1 - ## prioritizes left/right movement to up/down movement in diagonal inputs. - #if dir.x != 0 and dir.y != 0: - #dir.y = 0 - #return dir - -#func _process(delta: float) -> void: - ##check what group the next tile is in based on your raycast - #input_dir = get_player_input() - #if input_dir == Vector2.ZERO: - #return - #raycast.target_position = input_dir * TILE_SIZE - ## should make some sort of tileItem class - #var next_tile :Object = raycast.get_collider() - #if next_tile == null: - #return - #print(next_tile) - #position += input_dir * TILE_SIZE +func get_input_vector(event:InputEvent) -> Vector2: + # make vector representing player input + var dir := Vector2.ZERO + #dir.x = Input.get_axis("ui_left","ui_right") + #dir.y = Input.get_axis("ui_up","ui_down") + if event.is_action_pressed("ui_up"): + dir.y -= 1 + if event.is_action_pressed("ui_down"): + dir.y += 1 + if event.is_action_pressed("ui_left"): + dir.x -= 1 + if event.is_action_pressed("ui_right"): + dir.x += 1 + print(dir) + return dir func _unhandled_input(event: InputEvent) -> void: - if event.is_action_pressed("ui_up"): - print('up') \ No newline at end of file + input_dir = get_input_vector(event) + #check what group the next tile is in based on your raycast + if input_dir == Vector2.ZERO: + return + raycast.target_position = input_dir * TILE_SIZE + # should make some sort of tileItem class + var next_tile :Object = raycast.get_collider() + if next_tile != null: + print(next_tile) + position += input_dir * TILE_SIZE \ No newline at end of file From daaecffef41301a1f082360cc50fcd9f8f4a83f1 Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Sat, 16 Mar 2024 17:30:34 -0400 Subject: [PATCH 05/86] send ppl to boot --- README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b27ff06..4ddcfb5 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,21 @@ # The-Maze-With-GDYU A collaborative experiment between GDYU friends. - CURRENTLY: - + + +## CURRENTLY WORKING IN BOOTSTRAP BRANCH, LOOK IN THERE FOR UP TO DATE CONTRIBUTION INSTRUCTIONS + -Deciding a ticket system to make it easy to know how to help - + -Setting systems for contribution - + -Deciding how to iterate on gameplay Here's a [video](https://youtu.be/xjZsrdWe2jU) to understand what this is! - -Here's the [design doc](https://docs.google.com/document/d/1vs-uuo3EVE-bTyuviN5FSpdkm3ZyLSNCJJKOx5uJOF0/edit#heading=h.1jqugjgd3he3) to help contribute! -Read [contributing.md](/docs/contributing.md) before working on the repository. +Here's the [design doc](https://docs.google.com/document/d/1vs-uuo3EVE-bTyuviN5FSpdkm3ZyLSNCJJKOx5uJOF0/edit#heading=h.1jqugjgd3he3) to help contribute! + +Read [contributing.md](/docs/contributing.md) before working on the repository. DUE MAY 31 2024 23:59 From 86506c28733aea4c46edfafe88657fe0471f2feb Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Sat, 16 Mar 2024 17:37:23 -0400 Subject: [PATCH 06/86] writing instructions for the 999th time --- README.md | 14 ++++---------- docs/contributing.md | 11 ++++++----- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 4ddcfb5..14e442f 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,11 @@ # The-Maze-With-GDYU A collaborative experiment between GDYU friends. +## Current Goal: Bootstrap Version. +Prototype all of our gameplay mechanics and put them together by MARCH 20TH +To look at what needs to get done, view the [Github Project Page](https://github.com/orgs/GDYUClub/projects/1/views/1) -## CURRENTLY WORKING IN BOOTSTRAP BRANCH, LOOK IN THERE FOR UP TO DATE CONTRIBUTION INSTRUCTIONS - - -Deciding a ticket system to make it easy to know how to help - - -Setting systems for contribution - - -Deciding how to iterate on gameplay - - Here's a [video](https://youtu.be/xjZsrdWe2jU) to understand what this is! - +Here's a [video](https://youtu.be/xjZsrdWe2jU) to understand what this is! Here's the [design doc](https://docs.google.com/document/d/1vs-uuo3EVE-bTyuviN5FSpdkm3ZyLSNCJJKOx5uJOF0/edit#heading=h.1jqugjgd3he3) to help contribute! diff --git a/docs/contributing.md b/docs/contributing.md index 343ebe2..71602b4 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -1,8 +1,8 @@ # How to contribute to The Maze -- Follow a Git workflow of fork -> clone -> branch -> pr -> merge +- Follow a Git workflow of branch -> pr -> merge - If you're new to Git look [here](https://docs.github.com/en/get-started/quickstart/contributing-to-projects) - -## general +- we're currently working off of the ``bootstrap`` branch +## general - Keep file and folder names in `snake_case` (godot 4 standard) ## code @@ -10,10 +10,11 @@ - Use [Static Typing](https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/static_typing.html) for variables and functions. - put scenes and their scripts in the same directory - Name scenes after the root node. -- Name scripts the same name as the node they attach to +- variable and function names should be in snake_case, scenes/nodes referenced through code should be in camelCase +- Name scripts the same name as the node they attach to - Label custom data structures with Class names for type hint support - Connect signals and groups through code, NOT through the GUI. -- Each Scene should do one thing, each function should do one thing +- Each Scene should do one thing, each function should do one thing - Make [static classes](https://godottutorials.com/courses/introduction-to-gdscript/godot-tutorials-gdscript-20/) when able. - If a custom class/node doesn't have a position on screen or is instanced then removed, then pass it into the script as a object instead of putting in in the scene tree. - ^ reach out to jayden if you need elaboration on this one \ No newline at end of file From 31c744959e56be5d3114751d7357a252c6e5dcd4 Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Sun, 17 Mar 2024 10:56:42 -0400 Subject: [PATCH 07/86] tile collisions, reset ray before checking again --- src/main/main.tscn | 4 +++- src/player/player.gd | 33 +++++++++++++++++++-------------- src/scene-tiles/chest/chest.gd | 3 --- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/main/main.tscn b/src/main/main.tscn index 92c6fa0..b218b9e 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -3255,10 +3255,12 @@ sources/1 = SubResource("TileSetAtlasSource_ari5a") [node name="TileMap" type="TileMap" parent="."] tile_set = SubResource("TileSet_0u0tf") format = 2 +layer_0/name = "walls" layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2) +layer_1/tile_data = PackedInt32Array() [node name="chest" parent="." instance=ExtResource("2_win2x")] position = Vector2(112, 48) [node name="player" parent="." instance=ExtResource("2_ekt33")] -position = Vector2(16, 16) +position = Vector2(80, 48) diff --git a/src/player/player.gd b/src/player/player.gd index e56dd66..d03051e 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -2,18 +2,17 @@ extends Area2D @onready var raycast := $RayCast2D -var input_dir:= Vector2.ZERO -const TILE_SIZE:= 16 - +const TILE_SIZE := 16 func _init() -> void: - add_to_group('player') + add_to_group("player") + +func _ready() -> void: + raycast.collide_with_areas = true -func get_input_vector(event:InputEvent) -> Vector2: +func get_input_vector(event: InputEvent) -> Vector2: # make vector representing player input var dir := Vector2.ZERO - #dir.x = Input.get_axis("ui_left","ui_right") - #dir.y = Input.get_axis("ui_up","ui_down") if event.is_action_pressed("ui_up"): dir.y -= 1 if event.is_action_pressed("ui_down"): @@ -22,18 +21,24 @@ func get_input_vector(event:InputEvent) -> Vector2: dir.x -= 1 if event.is_action_pressed("ui_right"): dir.x += 1 - print(dir) return dir func _unhandled_input(event: InputEvent) -> void: - input_dir = get_input_vector(event) + var _input_dir := get_input_vector(event) #check what group the next tile is in based on your raycast - if input_dir == Vector2.ZERO: + if _input_dir != Vector2.ZERO: + _move(_input_dir) return - raycast.target_position = input_dir * TILE_SIZE - # should make some sort of tileItem class - var next_tile :Object = raycast.get_collider() + + +func _move(_input_dir:Vector2) -> void: + raycast.target_position = _input_dir * TILE_SIZE + # clear old raycast collison then get new one + raycast.force_raycast_update() + var next_tile: Object = raycast.get_collider() + if next_tile != null: print(next_tile) - position += input_dir * TILE_SIZE \ No newline at end of file + else: + position += _input_dir * TILE_SIZE \ No newline at end of file diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 94cffdd..fa2744b 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -9,6 +9,3 @@ func _ready() -> void: pass -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: - pass From 271029144db7109e5b829b8c4a746489c2d7ab6f Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Mon, 18 Mar 2024 14:36:09 -0400 Subject: [PATCH 08/86] text is splayed --- project.godot | 9 ++++++++ src/main/main.gd | 1 + src/main/main.tscn | 38 +++++++++++++++++++++++++++++----- src/main/ui.gd | 10 +++++++++ src/player/player.gd | 21 ++++++++++++++++++- src/player/player.tscn | 1 + src/scene-tiles/chest/chest.gd | 11 ++++++++++ 7 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 src/main/main.gd create mode 100644 src/main/ui.gd diff --git a/project.godot b/project.godot index 32b6d1c..3e84ed0 100644 --- a/project.godot +++ b/project.godot @@ -22,6 +22,15 @@ window/size/viewport_height=144 window/size/window_width_override=1280 window/size/window_height_override=720 window/stretch/mode="viewport" +window/stretch/scale_mode="integer" + +[input] + +inspect={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) +] +} [rendering] diff --git a/src/main/main.gd b/src/main/main.gd new file mode 100644 index 0000000..e251cf8 --- /dev/null +++ b/src/main/main.gd @@ -0,0 +1 @@ +extends Node2D diff --git a/src/main/main.tscn b/src/main/main.tscn index b218b9e..8eca979 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -1,8 +1,10 @@ -[gd_scene load_steps=6 format=3 uid="uid://cv5xm6ru2dkxf"] +[gd_scene load_steps=8 format=3 uid="uid://cv5xm6ru2dkxf"] +[ext_resource type="Script" path="res://src/main/main.gd" id="1_8hq0w"] [ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] [ext_resource type="PackedScene" uid="uid://bp6oyjqvoyffq" path="res://src/player/player.tscn" id="2_ekt33"] [ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="2_win2x"] +[ext_resource type="Script" path="res://src/main/ui.gd" id="4_o4xue"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ari5a"] texture = ExtResource("1_kghfi") @@ -3251,16 +3253,42 @@ physics_layer_0/collision_layer = 1 sources/1 = SubResource("TileSetAtlasSource_ari5a") [node name="Main" type="Node2D"] +script = ExtResource("1_8hq0w") -[node name="TileMap" type="TileMap" parent="."] +[node name="player" parent="." instance=ExtResource("2_ekt33")] +position = Vector2(80, 48) + +[node name="Map" type="Node2D" parent="."] + +[node name="TileMap" type="TileMap" parent="Map"] tile_set = SubResource("TileSet_0u0tf") format = 2 layer_0/name = "walls" layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2) layer_1/tile_data = PackedInt32Array() -[node name="chest" parent="." instance=ExtResource("2_win2x")] +[node name="chest" parent="Map" instance=ExtResource("2_win2x")] position = Vector2(112, 48) -[node name="player" parent="." instance=ExtResource("2_ekt33")] -position = Vector2(80, 48) +[node name="UI" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 0 +offset_right = 256.0 +offset_bottom = 144.0 +script = ExtResource("4_o4xue") + +[node name="Textbox" type="Panel" parent="UI"] +visible = false +layout_mode = 0 +offset_left = 16.0 +offset_top = 96.0 +offset_right = 240.0 +offset_bottom = 128.0 + +[node name="Text" type="Label" parent="UI/Textbox"] +layout_mode = 0 +offset_right = 224.0 +offset_bottom = 32.0 +theme_override_font_sizes/font_size = 10 +text = "I told you to not let Jayden make the ui bruh!!!" +autowrap_mode = 2 diff --git a/src/main/ui.gd b/src/main/ui.gd new file mode 100644 index 0000000..6f0f7e8 --- /dev/null +++ b/src/main/ui.gd @@ -0,0 +1,10 @@ +class_name UI +extends Control + +@onready var textbox:Panel = $Textbox + +func render_text(new_text): + textbox.visible = true + var textLabel = $Textbox/Text + textLabel.text = new_text + pass diff --git a/src/player/player.gd b/src/player/player.gd index d03051e..7ec94c3 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -1,3 +1,4 @@ +class_name player extends Area2D @onready var raycast := $RayCast2D @@ -30,6 +31,9 @@ func _unhandled_input(event: InputEvent) -> void: if _input_dir != Vector2.ZERO: _move(_input_dir) return + if event.is_action_pressed('inspect'): + _inspect() + func _move(_input_dir:Vector2) -> void: @@ -41,4 +45,19 @@ func _move(_input_dir:Vector2) -> void: if next_tile != null: print(next_tile) else: - position += _input_dir * TILE_SIZE \ No newline at end of file + position += _input_dir * TILE_SIZE + + +func _inspect() -> void: + raycast.force_raycast_update() + var inspect_tile: Object = raycast.get_collider() + if inspect_tile == null: + print('wow nothing!') + return + if inspect_tile.is_in_group('chest'): + inspect_tile._on_inspection() + #chest event + pass + + + pass diff --git a/src/player/player.tscn b/src/player/player.tscn index d916dbf..a3e2cd4 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -21,3 +21,4 @@ shape = SubResource("RectangleShape2D_v5s8d") [node name="RayCast2D" type="RayCast2D" parent="."] position = Vector2(8, 8) +target_position = Vector2(0, 16) diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index fa2744b..d3d39fe 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -1,5 +1,11 @@ extends Area2D +signal inspected +var opened:bool = false +@onready var sprite = $Sprite2D + +#bad solution but not a bad solution YET +@onready var ui:UI = get_parent().get_parent().get_node('UI') func _init() -> void: add_to_group('interact') @@ -8,4 +14,9 @@ func _init() -> void: func _ready() -> void: pass +func _on_inspection() -> void: + if !opened: + ui.render_text('I warned you about jayden making ui!!!') + $Sprite2D.frame = 1 + From 1854b6480b3723bc901c58679ae699ea87c619bd Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Mon, 18 Mar 2024 21:36:02 -0400 Subject: [PATCH 09/86] can't act while text is out, paint chests like tiles --- project.godot | 5 +++++ src/main/main.gd | 20 ++++++++++++++++++++ src/main/main.tscn | 15 ++++++++------- src/main/ui.gd | 23 ++++++++++++++++++++--- src/player/player.gd | 9 ++++++--- src/player/player.tscn | 2 +- src/scene-tiles/chest/chest.gd | 4 ++-- src/scene-tiles/chest/chest.tscn | 4 +--- 8 files changed, 63 insertions(+), 19 deletions(-) diff --git a/project.godot b/project.godot index 3e84ed0..8c5872d 100644 --- a/project.godot +++ b/project.godot @@ -31,6 +31,11 @@ inspect={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) ] } +adv_text={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) +] +} [rendering] diff --git a/src/main/main.gd b/src/main/main.gd index e251cf8..f9caa2e 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -1 +1,21 @@ extends Node2D + +@onready var ui:UI = $UI +@onready var player:Player = $Player + +var in_cutscene := false + +func _ready() -> void: + ui.text_rendered.connect(_start_cutscene) + ui.text_removed.connect(_end_cutscene) + pass + + +func _start_cutscene() -> void: + in_cutscene = true + player.is_actionable = false + +func _end_cutscene() -> void: + in_cutscene = false + await get_tree().create_timer(0.01).timeout # 10ms buffer hack to prevent input collision from text advancing and player input, could also solve by checking UI input in player _input event? + player.is_actionable = true \ No newline at end of file diff --git a/src/main/main.tscn b/src/main/main.tscn index 8eca979..19c4d23 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=8 format=3 uid="uid://cv5xm6ru2dkxf"] +[gd_scene load_steps=9 format=3 uid="uid://cv5xm6ru2dkxf"] [ext_resource type="Script" path="res://src/main/main.gd" id="1_8hq0w"] [ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] @@ -3248,14 +3248,18 @@ texture = ExtResource("1_kghfi") 18:0/0/physics_layer_0/angular_velocity = 0.0 18:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +[sub_resource type="TileSetScenesCollectionSource" id="TileSetScenesCollectionSource_mi6dp"] +scenes/1/scene = ExtResource("2_win2x") + [sub_resource type="TileSet" id="TileSet_0u0tf"] physics_layer_0/collision_layer = 1 sources/1 = SubResource("TileSetAtlasSource_ari5a") +sources/3 = SubResource("TileSetScenesCollectionSource_mi6dp") [node name="Main" type="Node2D"] script = ExtResource("1_8hq0w") -[node name="player" parent="." instance=ExtResource("2_ekt33")] +[node name="Player" parent="." instance=ExtResource("2_ekt33")] position = Vector2(80, 48) [node name="Map" type="Node2D" parent="."] @@ -3264,11 +3268,8 @@ position = Vector2(80, 48) tile_set = SubResource("TileSet_0u0tf") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2) -layer_1/tile_data = PackedInt32Array() - -[node name="chest" parent="Map" instance=ExtResource("2_win2x")] -position = Vector2(112, 48) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 196617, 0, 131072) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 262152, 3, 65536, 327689, 3, 65536, 327690, 3, 65536, 327691, 3, 65536, 262156, 3, 65536, 196620, 3, 65536, 131084, 3, 65536, 131083, 3, 65536, 131082, 3, 65536, 131081, 3, 65536, 196617, 3, 65536, 196616, 3, 65536, 327688, 3, 65536, 393224, 3, 65536, 393225, 3, 65536, 458761, 3, 65536, 458762, 3, 65536, 458763, 3, 65536, 458764, 3, 65536, 393228, 3, 65536, 393229, 3, 65536, 327693, 3, 65536, 262157, 3, 65536, 196621, 3, 65536, 131085, 3, 65536, 65548, 3, 65536, 65547, 3, 65536, 65546, 3, 65536, 65545, 3, 65536, 65544, 3, 65536, 65549, 3, 65536, 131086, 3, 65536, 196622, 3, 65536, 196623, 3, 65536) [node name="UI" type="Control" parent="."] layout_mode = 3 diff --git a/src/main/ui.gd b/src/main/ui.gd index 6f0f7e8..9d0ea58 100644 --- a/src/main/ui.gd +++ b/src/main/ui.gd @@ -2,9 +2,26 @@ class_name UI extends Control @onready var textbox:Panel = $Textbox +signal text_rendered +signal text_removed +signal text_advanced -func render_text(new_text): + +func render_text(new_text_arr) -> void: + #loop through the array and display the lines of text + text_rendered.emit() textbox.visible = true var textLabel = $Textbox/Text - textLabel.text = new_text - pass + #i = 0 + #while i < new_text_arr.length(): + for line in new_text_arr: + textLabel.text = line + await text_advanced + #await text_advanced + textbox.visible = false + text_removed.emit() + +func _input(event: InputEvent) -> void: + if event.is_action_pressed("adv_text"): + text_advanced.emit() + diff --git a/src/player/player.gd b/src/player/player.gd index 7ec94c3..db267f8 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -1,9 +1,10 @@ -class_name player +class_name Player extends Area2D @onready var raycast := $RayCast2D const TILE_SIZE := 16 +var is_actionable:= true func _init() -> void: add_to_group("player") @@ -25,7 +26,10 @@ func get_input_vector(event: InputEvent) -> Vector2: return dir -func _unhandled_input(event: InputEvent) -> void: +func _input(event: InputEvent) -> void: + # don't do anything if you aren't allowed to + if !is_actionable: + return var _input_dir := get_input_vector(event) #check what group the next tile is in based on your raycast if _input_dir != Vector2.ZERO: @@ -56,7 +60,6 @@ func _inspect() -> void: return if inspect_tile.is_in_group('chest'): inspect_tile._on_inspection() - #chest event pass diff --git a/src/player/player.tscn b/src/player/player.tscn index a3e2cd4..e362576 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -6,7 +6,7 @@ [sub_resource type="RectangleShape2D" id="RectangleShape2D_v5s8d"] size = Vector2(16, 16) -[node name="player" type="Area2D"] +[node name="Player" type="Area2D"] script = ExtResource("1_fqi5k") [node name="Sprite2D" type="Sprite2D" parent="."] diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index d3d39fe..dc4fbc6 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -5,7 +5,7 @@ var opened:bool = false @onready var sprite = $Sprite2D #bad solution but not a bad solution YET -@onready var ui:UI = get_parent().get_parent().get_node('UI') +@onready var ui:UI = get_parent().get_parent().get_parent().get_node('UI') func _init() -> void: add_to_group('interact') @@ -16,7 +16,7 @@ func _ready() -> void: func _on_inspection() -> void: if !opened: - ui.render_text('I warned you about jayden making ui!!!') + ui.render_text(['I warned you about jayden making ui!!!','now it is in an array','songboots would be nice']) $Sprite2D.frame = 1 diff --git a/src/scene-tiles/chest/chest.tscn b/src/scene-tiles/chest/chest.tscn index 67fb56a..9d1385c 100644 --- a/src/scene-tiles/chest/chest.tscn +++ b/src/scene-tiles/chest/chest.tscn @@ -6,16 +6,14 @@ [sub_resource type="RectangleShape2D" id="RectangleShape2D_vdfc5"] size = Vector2(16, 16) -[node name="chest" type="Area2D"] +[node name="Chest" type="Area2D"] script = ExtResource("1_j2k5u") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] -position = Vector2(8, 8) shape = SubResource("RectangleShape2D_vdfc5") [node name="Sprite2D" type="Sprite2D" parent="."] texture = ExtResource("1_dpxiw") -centered = false hframes = 2 region_enabled = true region_rect = Rect2(128, 96, 32, 16) From d11dade0c1c1cc002c76fab1f5f9c9d49d1b1d89 Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Tue, 19 Mar 2024 23:02:07 -0400 Subject: [PATCH 10/86] room shuffling and a fake ui --- assets/Not Jam UI Condensed 16.ttf | Bin 0 -> 118342 bytes assets/Not Jam UI Condensed 16.ttf.import | 33 + assets/white.png | Bin 0 -> 99 bytes assets/white.png.import | 34 + src/main/main.gd | 29 +- src/main/main.tscn | 3319 +-------------------- src/main/ui.gd | 2 + src/maps/map-1.tscn | 17 + src/maps/map-2.tscn | 15 + src/maps/map-3.tscn | 15 + src/maps/map.gd | 12 + src/player/player.gd | 9 +- src/player/player.tscn | 8 +- src/resources/map_tileset.tres | 3256 ++++++++++++++++++++ src/scene-tiles/chest/chest.gd | 3 +- src/scene-tiles/stairs/stairs.gd | 8 + src/scene-tiles/stairs/stairs.tscn | 18 + 17 files changed, 3509 insertions(+), 3269 deletions(-) create mode 100644 assets/Not Jam UI Condensed 16.ttf create mode 100644 assets/Not Jam UI Condensed 16.ttf.import create mode 100644 assets/white.png create mode 100644 assets/white.png.import create mode 100644 src/maps/map-1.tscn create mode 100644 src/maps/map-2.tscn create mode 100644 src/maps/map-3.tscn create mode 100644 src/maps/map.gd create mode 100644 src/resources/map_tileset.tres create mode 100644 src/scene-tiles/stairs/stairs.gd create mode 100644 src/scene-tiles/stairs/stairs.tscn diff --git a/assets/Not Jam UI Condensed 16.ttf b/assets/Not Jam UI Condensed 16.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c8767d2b229c3b58ca81886f1ffe1e9a29637a5c GIT binary patch literal 118342 zcmeHQ3(RFzbzbNHhgW&27(fvD1qvw0LlkMGx^*T}P_Y3-Q5zj+h5=z1WI(`bxveIe zXsS(ZG_g&6C8FY^(F9X9+_bgQps_w$HJV~7iCUXBv6|W_{Qb_^XWjYFx9`4dpL@=I z{KNhych*^ZJ@?vc?Y+}G7I+267L7(i|e#g!7z2aKXjtA4) zP22bE`p_G`3*A>AA+qJmH}Bndt6VP^z`t*oba)C@k8bZ$ zy%Dau)e=1vCQ6A)X4S1b^kV?bt-87$Nd0$L)pA#{Q?996R+KP;E5-YZcgsPtWd&+Q z)<57OjxUg^lirt#-&?IkuX)~!&JibTryN!L;AFT~6zgAGhhxK)0oc~?asE?@4nY|p zLayZSpVFq3#{ku5;M>c#5zYCw5gj}wt<+WNQ8+|n{i*B#Rh|{JtIZJ{?5CG)l^U)Z3V~rsc2HuOE>@xAMH;i16*a*zY?$P1L*NspPkp)un*ZP9)N0J zb&XU~Tv^o5T_KK#*fR+7$ms-i>Pph%@jr&I zc&%(HE(iV?{43j!ls}TY0@-K1Sr3Zx#8Smy7)F+4%fKd%W@^8=ATz-PON?D&AlZnWRc_%*af{s7?w#Z++N#uRM68WpUMLr1pBVQHyDD-{|ZJ+p} z$S1!m@+ruD2LAmGY<=!Jk$WE!`CA-+39`dyi2NP&{o_3%|MU})2L>Wv`<%!(wupQa zcK`Km$7hQC6vsb%NaVj>F7orUMSh7m{Oa=}zefAR(7XO7 zDT*7VSh+`vEm$iLxmb$BA0x%l?~&s1sQhD}A;k#~Npa!_q&R7(6l-sn;>q_*aq6K` zoQAeDAbaLjQaojV&u^r7+C@^F|89JKA;r_dcL6@nd=0h$ZbpIk>lhH3J0^rOIs7|AybM$;S$EB^O&HkZsSZzZq>|YBq$B&l6VH1CZa3TDWL6bkw z=O)u1G3b`Qz&`s&_<`pC%xjZtnQ>HRW1eKXg0Rx2mACxIE~H#ZW-zyPUU&MR zZJHW`b!;$suF$z4n3Ie-B*u@t^`je+$5o8U^oV@Sp8C%)m4AKE^e3o&WKvQsrtQ|V`&wNirL$}(SdyT;#du}#o_wJZbE?M(2GRsG~ zhQZ#D=*+KpAUA00P4y$F#fbf2{%3pAw6A_zFwh&ZuX?y&K`kP4lhzkM3gB+ZpDLHC zw=cd_J?g*0wsOpWaJf3++K+2o`-#>y#NEcV!J50Fw>h3r&=_CFk41w>+qo<1Z`T<@ z^Hw3RWwCZEE?wy(yF(n65v}Vkxt%pzMN?#CFZw2Nkd)u~`cLec=2&7+U zY!#7|`HuI)K`z$O(CApO>mGpZm-lkfR*wZB{wCs%=!~;G(-~)e#t*9OVb$EQW{w>t z2zuRhM7gIU`ha=>!q^^*90k$Q?A-K!bvO;T=<$JW>@J=o9IJyv=Qq94tkx7c-<#W(b zRy6Skc2oI=wZ57^sz>z^wBi@klJ{O}tEeQJpP0_L#c$D7-?H+h`jy&`WjlxA{24U! z4_MVRp7TfT!zO?0wVc1jCl>;!ftjW5VcuU)03{DTksaTmdvk8zdj+RpNf zs~v`^d~0CrC+`=Y^XQ11lq<0u4037M)Dz^SYtmIdHuth$fj-0Uk$!`3Zn=#PjjfT? zcIIQ;wbZZtr$bTy_sABW*RlOQI_rC``8aIi!Jc&1boIl4(_UBL`U>iZ`p5Ln^?`to z&3iuzpmwCI9)^})=2x8M+Ty1`pr5s&e139i>Ij{3)kqn6YMrA&OQnbTIPXS$l%H+e zSufjFeGDx=vo3tJ5H=&fV|+2WuI(((xQqB}@!^SnWa})i6D>_G#MTyW=bU2P$}#0< zKF(?7W5{w$XMEY#KFfcz2CbZRb*?iX1%r4 zHK(;2tbbZfRHMqT@KIOOZEH^Xxi%SBK860$TfkJPi&eFC$Q2EY1(VpQa2}+%X8{4N@es_J) zj0CVMGO;~Cv^}P07||bT42Vb; z*A7m5je6d4(H!x;*4~E@ff<`ah8)fTr;>xY>EsqQ7ih#NZ+Lb@R#g#;whzYVU3Bgs zd#XP=&at@8y8T2L=yHv8t}_8#bt$uewG-3PP{^Ym;B7~r_yc{zWP3|zh(6? zzlFP6Kl4S}(XZxgz;gJRAaLMnU5D#+)BbkHkL1VlGx=}%ANgPTwX7Gb#UaJv#nHtv z#c{=n#mU8~#Tms}#ks`=#j}cM7tbxW7MBz+EM8JvS-h-xW%24_N7}xt~CO?^auQ; zkLOI~Umr}it9+?2@RR&V)ssAj>s-o^=T4@##Z&dA^0EDC<+|!=Yqu?b-~Pqy$J*I` zD&Chqk#nG`%bqap_qOJ`bL?}OwPu92yU*6wIcX*h1x-~qkIZ2{;qVjqtMc~pYJrV_B)3x-Atj`8H2N~Dn3JMi;J~Rcbv`4YD~?h z{aMw#+NA9YSzlLN^(th2+8%=zf8J+rTttIogwIE|V;*vS2CIox2g^=3;uG{Y!f)2A z=DC&E%BRrc-|Telr$Vbg%IDX}F3+;^wejU!Bc239o^d$DX z_nPC}vvAEth0L$*3Yl)Xh& zvj)1#s~-^<_!HsN+6(x*`qxsvb4^=0-IeY~Uq*9?rLQf&rLQZ!`rW_e_h`-LcmFhc z&PS2gsYT;K4sy&Fjh_Gqrau>$+dhitzL}3JPSAKSLq4^JE?vTp<%)~2+sjQ4QY-ljOA)7 zy>GtF=FjnP7_Z_*oZJ2`z|7YLIOaCy%FNdT%1ySXxv$Wwr670FA?Vaz;b6|VGwd-P zZ*raU`y*$bQ^5p2;|2uKN7Z>))KGIM`X0w&Q_kcky~@upYHwQk0r^Qd+q3#VZ+cLp zezc_S6^4&$hUtvALnP}OMI|W`4{jH zn)ai7!zN##XU_EA<_oK?{HRLZdvMQa9+0v(wx5 zH=p+gHNCL`>EI*kCc_|)4gO$_8#eW~rnj{h;Sc)J)vuQFX1!~EV_+KBxV1e7E&i@_ zwrlBAev5C`^iyD9`g`^_Nb|eoOS3mdHMuH7A~4AFL_TXz$#$(@!?5&C>nHnR)|HiK zKAPa7y0dU+@LTk@`c)sxX}iMX!LUj0NAg%&_X9cS%p9XRx+{O@T*Jt~2dOI<2Xn@s zT3VdhdnuM?j@-D<8F!2zxGM5GH&ULo-lJ@Gd5uE^T61;pb>T-xqII&_=xzNyQ}8#F zI$io2MaO-#G#7_W{D7-X?Pmm9wa07XqrMh>_Q=$8$A!p1S()Z}t{t*l_`KmA@-E@; zRee_O75^JFUy%po>+&u64yyeC{X;PQh}8K#@8?ta`5Asjneop2bwAPTM!#ctU@uWl z^+n}}3g!yO-g_ z-!*Gp&l)p^*8N=N4_0&Z=n~GVZ;Y z;X5S9y{nLaBh%jp80&v5L+0JC6&b)mGrrL)M|J!I`MN!j8#eW-+|2n5KSzE<{NuX@ z(YNclNPcm#33LbHAtF)}IJ}@@%fz znVywt)t0K)vfGueekio`DPMJ-ko=zHjceS@S250M##3{g`K+2^I@?v;+S{5dLh2YX zUt3(qnj!09`lEPWE(D`o&H(ki!#NS)#IJG;gL$^r&wPpp{G~@5{OX-<_`|iNelpDS za%8t=)tuJg$za6uf1S@gWlzv333$Vp)7dY^3}Im_pBI_B0`Gd*_IQ1vNH&HX?>tpJ>}79PyZ>0{f> zJu4Sd^~U&Ee|!9Cs21159D0|$McyXkpW|Feu1=bBQ)rrl7UcP{H9zHQpsy?4!J`ek zA@(o1#>kIkIhkzVJOha3zP87pMAiZ2pEX_WD75Uw_@8>;&LzQj`2HoED1 zUFW_v-!q+SMDf&|SN`5>nQE}B{$QO$;1COq9u5rL5nXYX)Aks&_!m#F?tRfcmgD3^ zIayA{J&?2HT)9A=CC`@U%2v4qRo2rVI__gOWhQfGcg3xYDYK_l2Jy(Y#h(CsZmMT= zcJwz&lLlMo0)<^ipm+H}Gs8xHQv1@4yp<`g&cu-KbTsw74!(Cj*)%EBVl;HtRk4_I z4v}F~K3H`qQ#6ADzS_Rh6O)8$TBc@omn|*HR~42PnVK+1t)2HrvgzooAc?kIgtb7r1&( z=m;Mkk{$!!?EJ~s2wcmVnfWaoHPV>*4}5hYfZyUo9PRHF^|F%bNHesqG%}qt zp)DTG9FCal7-7~I;wPdB&m<*{!6mZs8E5}{UcHP<@@}E8N*826xhEriJdR3_wny}+ zoI+~`ispm&vK*qxJ4lN!Cf~MQ?I?`N@24LRmSz3DU1Ril)Yk_X&oNmu8fDU_?Fv~w z&_8VIx9FX(E$b*L#7M!W)Lw*;>0R;7evL^Z=jcKl{W4VgLVc$y~<6#q@drqn!5oqNc&zYT9N(89Y9Ot7cbrd0O$hYNZ zebu{`W_mwv?m3ydyNmH5L_Vr@4j~5`_``(ra|?{moxk=QUN`(s#k>A~f%R?i&NbzG zC3Wwl{F_)~^X6xJjJNf-t^AW=0B5;~vwfaB?i_35yH=K>deI#pgF2)68-YQ_Y32`_ za#{hws-*k``8-_ZW9>>;7_}4gi`u!L3#%Lqz}O0lwfoT$#KFs@@}=^N;N2NBx`**$ z`6#Mqll&pDK4z|l!zLbN;G*g3X9QaNGxVwV=~w2*3q+rAHV#%YEyOwPQ)czv<8B-$R)Gp%1{#``EB z97g6^d@=d9?P^D1OkU{!&>`l%mrZX-i-#5LjKILb>s(T#8aLRpP$~)wyUJJ(M^E}#O zzp$e@n3{XaAJoRM&aOIVna(+@dKjkq!8LF0eIm8Q_D5@OBEQN9dmhbAg`A_>9)lJ? z(;1&uugbAL3s*S{vL1_H>Cb?m^!Dzg@xLe3d@tmtt8r@{K>&R;>)ggZv4Kb5uSR^D z^9`Y1oKC)`wpA+qGJ|)7Q8S1NUrdjH1cOK-p{`HgL`(G8!?EK>9lsl^lJOE z>G$`>2Y51h(w=hayhnF^&trK(?WubK%^#iv(U19#AL6$n=Dn!7#ZTkX_WFm)nRB`y zO&!(!ux;E`51uW+TLe#~3!}L@{vYXPo7k&N%ZEUaq$@U2}h{%;e~E z!pZpww_W8a)o_qcJVy-2%SCIR;sdl9AI4oxKeC!j1$yIad2(+zRu>F<8`N{OR_%Os zeAG@ow=z8%5$z!y8Jj8G&bZ1e6zT2V$2$6f@9cx()%!Gh|E|+ibd zx4^*xo^juQ9VDoIaJVY^&O@HngKH1m=ffcFO0F^cv%uQ8Du<-o=mD?_XHQ1$HC^!$ zgrc!o)V}?2W6zn?FYW8dKke55Ev2W_5AJVl|EY38wWanm#^=2PRr2+VDi%S6H9`y# zvay+`d|m0P=QJof(69ZYhvTY)*Fvp=)U|bLeyUQ{6ZNO9|1J5=UA5+lLZr;Z+*Ce= zo1On0bU;>9uf0yX#utBw>%CYXHtF9ef9t%)%I!zK#$$WqfN#*03+S~zwl~5_K3M&R zP5n&g>z|AV_XJ5_YyL=o*bc7AHR5TmA;{LG`n32gy7x+I@4!uVE!+`5<1Ei~#@q6% zye0P(Fv!XfagSdw-2ZOMcJ;q0s(w^qb;hPvX23_89MEh1Y;S~*XLIp8bTs-&)TSI-zC=Rwu%*W@qAeVcb(*6joW<>MBsu3?kT)u7qiHtS>S z{zxBHl~uh=52~5;@jA->v%JY4i66_gUa$S=NIeP|E@NF(ev8kds~&~SZ{aEzgDfB8 z)AqLfsd6VGo(@k>45wVb=ekC7R&v${IAy(7SL_}lUjqvC4eLCNWV`BD$oFuxondg6 zNuv!vn!8q_L!YOowlg2&sxJmp`9-Sp!@W_)UfE5AZZ&Z5WkupHwm$I#-l=&VoiRJqf@ zh$m;T?)PfoLu~AeSDA{UVO4XK3I+^K3^Xn z2H6Md<0ECY_-1{4jGSHk3wlv(!QD(bc%`V1(chIr>SOeG<(c&{`n$5VK1P36USA)h zzbl`vkI~YRjL&Usv z8HYE@ouKUmb+??eb?bST@4a>Hvh91;UV7=;*1b3F+;!8wT|3v#zwnA(yKlR3`z;Y_ zqx-6)7tsxl(fN~Bgzc5$+T`L#(gW&%nXvqyZ z0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX z0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX z0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX z0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX Z0yzRX0yzRX0yzRX0yzRX0yB%i{{#Nuf{FkD literal 0 HcmV?d00001 diff --git a/assets/Not Jam UI Condensed 16.ttf.import b/assets/Not Jam UI Condensed 16.ttf.import new file mode 100644 index 0000000..dd00f06 --- /dev/null +++ b/assets/Not Jam UI Condensed 16.ttf.import @@ -0,0 +1,33 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://ddjw625xpmwtc" +path="res://.godot/imported/Not Jam UI Condensed 16.ttf-3435f3f176c8ad289519e69fb68982d4.fontdata" + +[deps] + +source_file="res://assets/Not Jam UI Condensed 16.ttf" +dest_files=["res://.godot/imported/Not Jam UI Condensed 16.ttf-3435f3f176c8ad289519e69fb68982d4.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/assets/white.png b/assets/white.png new file mode 100644 index 0000000000000000000000000000000000000000..a449decfda83ba650f4418e380e7f90a7f528cd7 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le v|NQ^|zn+bYL0EN`JFkRk!j*=DDGUtRr&wf`KP(LfDrE3<^>bP0l+XkKc$*s_ literal 0 HcmV?d00001 diff --git a/assets/white.png.import b/assets/white.png.import new file mode 100644 index 0000000..0d60315 --- /dev/null +++ b/assets/white.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://5kstmna3yb6t" +path="res://.godot/imported/white.png-936ea7d0834e1e21adf362ba74ff2135.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/white.png" +dest_files=["res://.godot/imported/white.png-936ea7d0834e1e21adf362ba74ff2135.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 diff --git a/src/main/main.gd b/src/main/main.gd index f9caa2e..0fa48e3 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -2,14 +2,41 @@ extends Node2D @onready var ui:UI = $UI @onready var player:Player = $Player +@onready var current_map:Node2D = $Map var in_cutscene := false +var maps:Dictionary = {0:preload('res://src/maps/map-1.tscn'),1:preload('res://src/maps/map-2.tscn'),2:preload('res://src/maps/map-3.tscn')} +var shuffled_maps:Array = [] + +var current_map_id + func _ready() -> void: ui.text_rendered.connect(_start_cutscene) ui.text_removed.connect(_end_cutscene) + player.walked_into_stairs.connect(swap_map) pass +func swap_map() -> void: + #reshuffle rooms if we've visted them all + if shuffled_maps.size() == 0: + shuffled_maps = Array(range(maps.size())) + shuffled_maps.shuffle() + #pick new room from remaining choices + var next_map_id :int = shuffled_maps.pop_front() + var nextMap:Node2D = maps[next_map_id].instantiate() + + #load new map + current_map.queue_free() + add_child(nextMap) + current_map = nextMap + + #move the player to the spawn point + var playerSpawnMarker:Marker2D = nextMap.get_node('PlayerSpawn') + player.position = playerSpawnMarker.position + + + func _start_cutscene() -> void: in_cutscene = true @@ -18,4 +45,4 @@ func _start_cutscene() -> void: func _end_cutscene() -> void: in_cutscene = false await get_tree().create_timer(0.01).timeout # 10ms buffer hack to prevent input collision from text advancing and player input, could also solve by checking UI input in player _input event? - player.is_actionable = true \ No newline at end of file + player.is_actionable = true diff --git a/src/main/main.tscn b/src/main/main.tscn index 19c4d23..0da652a 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -1,3260 +1,12 @@ -[gd_scene load_steps=9 format=3 uid="uid://cv5xm6ru2dkxf"] +[gd_scene load_steps=8 format=3 uid="uid://cv5xm6ru2dkxf"] [ext_resource type="Script" path="res://src/main/main.gd" id="1_8hq0w"] [ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] [ext_resource type="PackedScene" uid="uid://bp6oyjqvoyffq" path="res://src/player/player.tscn" id="2_ekt33"] -[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="2_win2x"] +[ext_resource type="PackedScene" uid="uid://deqm4to4ptnq0" path="res://src/maps/map-1.tscn" id="3_w444g"] [ext_resource type="Script" path="res://src/main/ui.gd" id="4_o4xue"] - -[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ari5a"] -texture = ExtResource("1_kghfi") -1:0/0 = 0 -1:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:0/0/physics_layer_0/angular_velocity = 0.0 -2:0/0 = 0 -2:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:0/0/physics_layer_0/angular_velocity = 0.0 -3:0/0 = 0 -3:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:0/0/physics_layer_0/angular_velocity = 0.0 -4:0/0 = 0 -4:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:0/0/physics_layer_0/angular_velocity = 0.0 -5:0/0 = 0 -5:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:0/0/physics_layer_0/angular_velocity = 0.0 -6:0/0 = 0 -6:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:0/0/physics_layer_0/angular_velocity = 0.0 -7:0/0 = 0 -7:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:0/0/physics_layer_0/angular_velocity = 0.0 -8:0/0 = 0 -8:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:0/0/physics_layer_0/angular_velocity = 0.0 -9:0/0 = 0 -9:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:0/0/physics_layer_0/angular_velocity = 0.0 -10:0/0 = 0 -10:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:0/0/physics_layer_0/angular_velocity = 0.0 -11:0/0 = 0 -11:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:0/0/physics_layer_0/angular_velocity = 0.0 -12:0/0 = 0 -12:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:0/0/physics_layer_0/angular_velocity = 0.0 -13:0/0 = 0 -13:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:0/0/physics_layer_0/angular_velocity = 0.0 -14:0/0 = 0 -14:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:0/0/physics_layer_0/angular_velocity = 0.0 -15:0/0 = 0 -15:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:0/0/physics_layer_0/angular_velocity = 0.0 -16:0/0 = 0 -16:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:0/0/physics_layer_0/angular_velocity = 0.0 -17:0/0 = 0 -17:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:0/0/physics_layer_0/angular_velocity = 0.0 -19:0/0 = 0 -19:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:0/0/physics_layer_0/angular_velocity = 0.0 -19:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -20:0/0 = 0 -20:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:0/0/physics_layer_0/angular_velocity = 0.0 -20:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -21:0/0 = 0 -21:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:0/0/physics_layer_0/angular_velocity = 0.0 -22:0/0 = 0 -22:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:0/0/physics_layer_0/angular_velocity = 0.0 -23:0/0 = 0 -23:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:0/0/physics_layer_0/angular_velocity = 0.0 -24:0/0 = 0 -24:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:0/0/physics_layer_0/angular_velocity = 0.0 -25:0/0 = 0 -25:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:0/0/physics_layer_0/angular_velocity = 0.0 -26:0/0 = 0 -26:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:0/0/physics_layer_0/angular_velocity = 0.0 -27:0/0 = 0 -27:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:0/0/physics_layer_0/angular_velocity = 0.0 -28:0/0 = 0 -28:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:0/0/physics_layer_0/angular_velocity = 0.0 -29:0/0 = 0 -29:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:0/0/physics_layer_0/angular_velocity = 0.0 -30:0/0 = 0 -30:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:0/0/physics_layer_0/angular_velocity = 0.0 -31:0/0 = 0 -31:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:0/0/physics_layer_0/angular_velocity = 0.0 -32:0/0 = 0 -32:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:0/0/physics_layer_0/angular_velocity = 0.0 -33:0/0 = 0 -33:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:0/0/physics_layer_0/angular_velocity = 0.0 -34:0/0 = 0 -34:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:0/0/physics_layer_0/angular_velocity = 0.0 -35:0/0 = 0 -35:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:0/0/physics_layer_0/angular_velocity = 0.0 -36:0/0 = 0 -36:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:0/0/physics_layer_0/angular_velocity = 0.0 -37:0/0 = 0 -37:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:0/0/physics_layer_0/angular_velocity = 0.0 -38:0/0 = 0 -38:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:0/0/physics_layer_0/angular_velocity = 0.0 -39:0/0 = 0 -39:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:0/0/physics_layer_0/angular_velocity = 0.0 -40:0/0 = 0 -40:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:0/0/physics_layer_0/angular_velocity = 0.0 -41:0/0 = 0 -41:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:0/0/physics_layer_0/angular_velocity = 0.0 -42:0/0 = 0 -42:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:0/0/physics_layer_0/angular_velocity = 0.0 -43:0/0 = 0 -43:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:0/0/physics_layer_0/angular_velocity = 0.0 -44:0/0 = 0 -44:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:0/0/physics_layer_0/angular_velocity = 0.0 -45:0/0 = 0 -45:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:0/0/physics_layer_0/angular_velocity = 0.0 -46:0/0 = 0 -46:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:0/0/physics_layer_0/angular_velocity = 0.0 -47:0/0 = 0 -47:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:0/0/physics_layer_0/angular_velocity = 0.0 -48:0/0 = 0 -48:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:0/0/physics_layer_0/angular_velocity = 0.0 -0:1/0 = 0 -0:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:1/0/physics_layer_0/angular_velocity = 0.0 -1:1/0 = 0 -1:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:1/0/physics_layer_0/angular_velocity = 0.0 -2:1/0 = 0 -2:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:1/0/physics_layer_0/angular_velocity = 0.0 -3:1/0 = 0 -3:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:1/0/physics_layer_0/angular_velocity = 0.0 -4:1/0 = 0 -4:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:1/0/physics_layer_0/angular_velocity = 0.0 -5:1/0 = 0 -5:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:1/0/physics_layer_0/angular_velocity = 0.0 -6:1/0 = 0 -6:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:1/0/physics_layer_0/angular_velocity = 0.0 -7:1/0 = 0 -7:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:1/0/physics_layer_0/angular_velocity = 0.0 -8:1/0 = 0 -8:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:1/0/physics_layer_0/angular_velocity = 0.0 -9:1/0 = 0 -9:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:1/0/physics_layer_0/angular_velocity = 0.0 -10:1/0 = 0 -10:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:1/0/physics_layer_0/angular_velocity = 0.0 -11:1/0 = 0 -11:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:1/0/physics_layer_0/angular_velocity = 0.0 -12:1/0 = 0 -12:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:1/0/physics_layer_0/angular_velocity = 0.0 -13:1/0 = 0 -13:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:1/0/physics_layer_0/angular_velocity = 0.0 -14:1/0 = 0 -14:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:1/0/physics_layer_0/angular_velocity = 0.0 -15:1/0 = 0 -15:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:1/0/physics_layer_0/angular_velocity = 0.0 -16:1/0 = 0 -16:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:1/0/physics_layer_0/angular_velocity = 0.0 -17:1/0 = 0 -17:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:1/0/physics_layer_0/angular_velocity = 0.0 -18:1/0 = 0 -18:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:1/0/physics_layer_0/angular_velocity = 0.0 -18:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -19:1/0 = 0 -19:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:1/0/physics_layer_0/angular_velocity = 0.0 -20:1/0 = 0 -20:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:1/0/physics_layer_0/angular_velocity = 0.0 -20:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -21:1/0 = 0 -21:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:1/0/physics_layer_0/angular_velocity = 0.0 -22:1/0 = 0 -22:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:1/0/physics_layer_0/angular_velocity = 0.0 -23:1/0 = 0 -23:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:1/0/physics_layer_0/angular_velocity = 0.0 -24:1/0 = 0 -24:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:1/0/physics_layer_0/angular_velocity = 0.0 -25:1/0 = 0 -25:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:1/0/physics_layer_0/angular_velocity = 0.0 -26:1/0 = 0 -26:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:1/0/physics_layer_0/angular_velocity = 0.0 -27:1/0 = 0 -27:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:1/0/physics_layer_0/angular_velocity = 0.0 -28:1/0 = 0 -28:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:1/0/physics_layer_0/angular_velocity = 0.0 -29:1/0 = 0 -29:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:1/0/physics_layer_0/angular_velocity = 0.0 -30:1/0 = 0 -30:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:1/0/physics_layer_0/angular_velocity = 0.0 -31:1/0 = 0 -31:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:1/0/physics_layer_0/angular_velocity = 0.0 -32:1/0 = 0 -32:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:1/0/physics_layer_0/angular_velocity = 0.0 -33:1/0 = 0 -33:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:1/0/physics_layer_0/angular_velocity = 0.0 -34:1/0 = 0 -34:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:1/0/physics_layer_0/angular_velocity = 0.0 -35:1/0 = 0 -35:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:1/0/physics_layer_0/angular_velocity = 0.0 -36:1/0 = 0 -36:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:1/0/physics_layer_0/angular_velocity = 0.0 -37:1/0 = 0 -37:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:1/0/physics_layer_0/angular_velocity = 0.0 -38:1/0 = 0 -38:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:1/0/physics_layer_0/angular_velocity = 0.0 -39:1/0 = 0 -39:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:1/0/physics_layer_0/angular_velocity = 0.0 -40:1/0 = 0 -40:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:1/0/physics_layer_0/angular_velocity = 0.0 -41:1/0 = 0 -41:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:1/0/physics_layer_0/angular_velocity = 0.0 -42:1/0 = 0 -42:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:1/0/physics_layer_0/angular_velocity = 0.0 -43:1/0 = 0 -43:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:1/0/physics_layer_0/angular_velocity = 0.0 -44:1/0 = 0 -44:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:1/0/physics_layer_0/angular_velocity = 0.0 -45:1/0 = 0 -45:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:1/0/physics_layer_0/angular_velocity = 0.0 -46:1/0 = 0 -46:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:1/0/physics_layer_0/angular_velocity = 0.0 -47:1/0 = 0 -47:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:1/0/physics_layer_0/angular_velocity = 0.0 -48:1/0 = 0 -48:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:1/0/physics_layer_0/angular_velocity = 0.0 -0:2/0 = 0 -0:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:2/0/physics_layer_0/angular_velocity = 0.0 -1:2/0 = 0 -1:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:2/0/physics_layer_0/angular_velocity = 0.0 -2:2/0 = 0 -2:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:2/0/physics_layer_0/angular_velocity = 0.0 -3:2/0 = 0 -3:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:2/0/physics_layer_0/angular_velocity = 0.0 -4:2/0 = 0 -4:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:2/0/physics_layer_0/angular_velocity = 0.0 -5:2/0 = 0 -5:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:2/0/physics_layer_0/angular_velocity = 0.0 -6:2/0 = 0 -6:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:2/0/physics_layer_0/angular_velocity = 0.0 -7:2/0 = 0 -7:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:2/0/physics_layer_0/angular_velocity = 0.0 -8:2/0 = 0 -8:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:2/0/physics_layer_0/angular_velocity = 0.0 -9:2/0 = 0 -9:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:2/0/physics_layer_0/angular_velocity = 0.0 -10:2/0 = 0 -10:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:2/0/physics_layer_0/angular_velocity = 0.0 -11:2/0 = 0 -11:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:2/0/physics_layer_0/angular_velocity = 0.0 -12:2/0 = 0 -12:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:2/0/physics_layer_0/angular_velocity = 0.0 -13:2/0 = 0 -13:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:2/0/physics_layer_0/angular_velocity = 0.0 -14:2/0 = 0 -14:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:2/0/physics_layer_0/angular_velocity = 0.0 -15:2/0 = 0 -15:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:2/0/physics_layer_0/angular_velocity = 0.0 -16:2/0 = 0 -16:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:2/0/physics_layer_0/angular_velocity = 0.0 -17:2/0 = 0 -17:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:2/0/physics_layer_0/angular_velocity = 0.0 -18:2/0 = 0 -18:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:2/0/physics_layer_0/angular_velocity = 0.0 -18:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -19:2/0 = 0 -19:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:2/0/physics_layer_0/angular_velocity = 0.0 -19:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -20:2/0 = 0 -20:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:2/0/physics_layer_0/angular_velocity = 0.0 -20:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -21:2/0 = 0 -21:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:2/0/physics_layer_0/angular_velocity = 0.0 -22:2/0 = 0 -22:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:2/0/physics_layer_0/angular_velocity = 0.0 -23:2/0 = 0 -23:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:2/0/physics_layer_0/angular_velocity = 0.0 -24:2/0 = 0 -24:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:2/0/physics_layer_0/angular_velocity = 0.0 -25:2/0 = 0 -25:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:2/0/physics_layer_0/angular_velocity = 0.0 -26:2/0 = 0 -26:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:2/0/physics_layer_0/angular_velocity = 0.0 -27:2/0 = 0 -27:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:2/0/physics_layer_0/angular_velocity = 0.0 -28:2/0 = 0 -28:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:2/0/physics_layer_0/angular_velocity = 0.0 -29:2/0 = 0 -29:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:2/0/physics_layer_0/angular_velocity = 0.0 -30:2/0 = 0 -30:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:2/0/physics_layer_0/angular_velocity = 0.0 -31:2/0 = 0 -31:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:2/0/physics_layer_0/angular_velocity = 0.0 -32:2/0 = 0 -32:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:2/0/physics_layer_0/angular_velocity = 0.0 -33:2/0 = 0 -33:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:2/0/physics_layer_0/angular_velocity = 0.0 -34:2/0 = 0 -34:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:2/0/physics_layer_0/angular_velocity = 0.0 -35:2/0 = 0 -35:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:2/0/physics_layer_0/angular_velocity = 0.0 -36:2/0 = 0 -36:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:2/0/physics_layer_0/angular_velocity = 0.0 -37:2/0 = 0 -37:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:2/0/physics_layer_0/angular_velocity = 0.0 -38:2/0 = 0 -38:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:2/0/physics_layer_0/angular_velocity = 0.0 -39:2/0 = 0 -39:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:2/0/physics_layer_0/angular_velocity = 0.0 -40:2/0 = 0 -40:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:2/0/physics_layer_0/angular_velocity = 0.0 -41:2/0 = 0 -41:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:2/0/physics_layer_0/angular_velocity = 0.0 -42:2/0 = 0 -42:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:2/0/physics_layer_0/angular_velocity = 0.0 -43:2/0 = 0 -43:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:2/0/physics_layer_0/angular_velocity = 0.0 -44:2/0 = 0 -44:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:2/0/physics_layer_0/angular_velocity = 0.0 -45:2/0 = 0 -45:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:2/0/physics_layer_0/angular_velocity = 0.0 -46:2/0 = 0 -46:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:2/0/physics_layer_0/angular_velocity = 0.0 -47:2/0 = 0 -47:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:2/0/physics_layer_0/angular_velocity = 0.0 -48:2/0 = 0 -48:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:2/0/physics_layer_0/angular_velocity = 0.0 -0:3/0 = 0 -0:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:3/0/physics_layer_0/angular_velocity = 0.0 -1:3/0 = 0 -1:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:3/0/physics_layer_0/angular_velocity = 0.0 -2:3/0 = 0 -2:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:3/0/physics_layer_0/angular_velocity = 0.0 -3:3/0 = 0 -3:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:3/0/physics_layer_0/angular_velocity = 0.0 -4:3/0 = 0 -4:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:3/0/physics_layer_0/angular_velocity = 0.0 -5:3/0 = 0 -5:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:3/0/physics_layer_0/angular_velocity = 0.0 -6:3/0 = 0 -6:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:3/0/physics_layer_0/angular_velocity = 0.0 -7:3/0 = 0 -7:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:3/0/physics_layer_0/angular_velocity = 0.0 -8:3/0 = 0 -8:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:3/0/physics_layer_0/angular_velocity = 0.0 -9:3/0 = 0 -9:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:3/0/physics_layer_0/angular_velocity = 0.0 -10:3/0 = 0 -10:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:3/0/physics_layer_0/angular_velocity = 0.0 -11:3/0 = 0 -11:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:3/0/physics_layer_0/angular_velocity = 0.0 -12:3/0 = 0 -12:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:3/0/physics_layer_0/angular_velocity = 0.0 -13:3/0 = 0 -13:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:3/0/physics_layer_0/angular_velocity = 0.0 -14:3/0 = 0 -14:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:3/0/physics_layer_0/angular_velocity = 0.0 -15:3/0 = 0 -15:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:3/0/physics_layer_0/angular_velocity = 0.0 -16:3/0 = 0 -16:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:3/0/physics_layer_0/angular_velocity = 0.0 -17:3/0 = 0 -17:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:3/0/physics_layer_0/angular_velocity = 0.0 -18:3/0 = 0 -18:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:3/0/physics_layer_0/angular_velocity = 0.0 -19:3/0 = 0 -19:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:3/0/physics_layer_0/angular_velocity = 0.0 -20:3/0 = 0 -20:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:3/0/physics_layer_0/angular_velocity = 0.0 -21:3/0 = 0 -21:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:3/0/physics_layer_0/angular_velocity = 0.0 -22:3/0 = 0 -22:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:3/0/physics_layer_0/angular_velocity = 0.0 -23:3/0 = 0 -23:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:3/0/physics_layer_0/angular_velocity = 0.0 -24:3/0 = 0 -24:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:3/0/physics_layer_0/angular_velocity = 0.0 -25:3/0 = 0 -25:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:3/0/physics_layer_0/angular_velocity = 0.0 -26:3/0 = 0 -26:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:3/0/physics_layer_0/angular_velocity = 0.0 -27:3/0 = 0 -27:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:3/0/physics_layer_0/angular_velocity = 0.0 -28:3/0 = 0 -28:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:3/0/physics_layer_0/angular_velocity = 0.0 -29:3/0 = 0 -29:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:3/0/physics_layer_0/angular_velocity = 0.0 -30:3/0 = 0 -30:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:3/0/physics_layer_0/angular_velocity = 0.0 -31:3/0 = 0 -31:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:3/0/physics_layer_0/angular_velocity = 0.0 -32:3/0 = 0 -32:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:3/0/physics_layer_0/angular_velocity = 0.0 -33:3/0 = 0 -33:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:3/0/physics_layer_0/angular_velocity = 0.0 -34:3/0 = 0 -34:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:3/0/physics_layer_0/angular_velocity = 0.0 -35:3/0 = 0 -35:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:3/0/physics_layer_0/angular_velocity = 0.0 -36:3/0 = 0 -36:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:3/0/physics_layer_0/angular_velocity = 0.0 -37:3/0 = 0 -37:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:3/0/physics_layer_0/angular_velocity = 0.0 -38:3/0 = 0 -38:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:3/0/physics_layer_0/angular_velocity = 0.0 -39:3/0 = 0 -39:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:3/0/physics_layer_0/angular_velocity = 0.0 -40:3/0 = 0 -40:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:3/0/physics_layer_0/angular_velocity = 0.0 -41:3/0 = 0 -41:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:3/0/physics_layer_0/angular_velocity = 0.0 -42:3/0 = 0 -42:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:3/0/physics_layer_0/angular_velocity = 0.0 -43:3/0 = 0 -43:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:3/0/physics_layer_0/angular_velocity = 0.0 -44:3/0 = 0 -44:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:3/0/physics_layer_0/angular_velocity = 0.0 -45:3/0 = 0 -45:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:3/0/physics_layer_0/angular_velocity = 0.0 -46:3/0 = 0 -46:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:3/0/physics_layer_0/angular_velocity = 0.0 -47:3/0 = 0 -47:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:3/0/physics_layer_0/angular_velocity = 0.0 -48:3/0 = 0 -48:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:3/0/physics_layer_0/angular_velocity = 0.0 -0:4/0 = 0 -0:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:4/0/physics_layer_0/angular_velocity = 0.0 -1:4/0 = 0 -1:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:4/0/physics_layer_0/angular_velocity = 0.0 -2:4/0 = 0 -2:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:4/0/physics_layer_0/angular_velocity = 0.0 -3:4/0 = 0 -3:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:4/0/physics_layer_0/angular_velocity = 0.0 -4:4/0 = 0 -4:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:4/0/physics_layer_0/angular_velocity = 0.0 -5:4/0 = 0 -5:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:4/0/physics_layer_0/angular_velocity = 0.0 -6:4/0 = 0 -6:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:4/0/physics_layer_0/angular_velocity = 0.0 -7:4/0 = 0 -7:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:4/0/physics_layer_0/angular_velocity = 0.0 -8:4/0 = 0 -8:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:4/0/physics_layer_0/angular_velocity = 0.0 -9:4/0 = 0 -9:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:4/0/physics_layer_0/angular_velocity = 0.0 -10:4/0 = 0 -10:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:4/0/physics_layer_0/angular_velocity = 0.0 -11:4/0 = 0 -11:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:4/0/physics_layer_0/angular_velocity = 0.0 -12:4/0 = 0 -12:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:4/0/physics_layer_0/angular_velocity = 0.0 -13:4/0 = 0 -13:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:4/0/physics_layer_0/angular_velocity = 0.0 -14:4/0 = 0 -14:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:4/0/physics_layer_0/angular_velocity = 0.0 -15:4/0 = 0 -15:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:4/0/physics_layer_0/angular_velocity = 0.0 -16:4/0 = 0 -16:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:4/0/physics_layer_0/angular_velocity = 0.0 -17:4/0 = 0 -17:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:4/0/physics_layer_0/angular_velocity = 0.0 -18:4/0 = 0 -18:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:4/0/physics_layer_0/angular_velocity = 0.0 -19:4/0 = 0 -19:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:4/0/physics_layer_0/angular_velocity = 0.0 -20:4/0 = 0 -20:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:4/0/physics_layer_0/angular_velocity = 0.0 -21:4/0 = 0 -21:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:4/0/physics_layer_0/angular_velocity = 0.0 -22:4/0 = 0 -22:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:4/0/physics_layer_0/angular_velocity = 0.0 -23:4/0 = 0 -23:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:4/0/physics_layer_0/angular_velocity = 0.0 -24:4/0 = 0 -24:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:4/0/physics_layer_0/angular_velocity = 0.0 -25:4/0 = 0 -25:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:4/0/physics_layer_0/angular_velocity = 0.0 -26:4/0 = 0 -26:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:4/0/physics_layer_0/angular_velocity = 0.0 -27:4/0 = 0 -27:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:4/0/physics_layer_0/angular_velocity = 0.0 -28:4/0 = 0 -28:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:4/0/physics_layer_0/angular_velocity = 0.0 -29:4/0 = 0 -29:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:4/0/physics_layer_0/angular_velocity = 0.0 -30:4/0 = 0 -30:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:4/0/physics_layer_0/angular_velocity = 0.0 -31:4/0 = 0 -31:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:4/0/physics_layer_0/angular_velocity = 0.0 -32:4/0 = 0 -32:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:4/0/physics_layer_0/angular_velocity = 0.0 -33:4/0 = 0 -33:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:4/0/physics_layer_0/angular_velocity = 0.0 -34:4/0 = 0 -34:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:4/0/physics_layer_0/angular_velocity = 0.0 -35:4/0 = 0 -35:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:4/0/physics_layer_0/angular_velocity = 0.0 -36:4/0 = 0 -36:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:4/0/physics_layer_0/angular_velocity = 0.0 -37:4/0 = 0 -37:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:4/0/physics_layer_0/angular_velocity = 0.0 -38:4/0 = 0 -38:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:4/0/physics_layer_0/angular_velocity = 0.0 -39:4/0 = 0 -39:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:4/0/physics_layer_0/angular_velocity = 0.0 -40:4/0 = 0 -40:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:4/0/physics_layer_0/angular_velocity = 0.0 -41:4/0 = 0 -41:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:4/0/physics_layer_0/angular_velocity = 0.0 -42:4/0 = 0 -42:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:4/0/physics_layer_0/angular_velocity = 0.0 -43:4/0 = 0 -43:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:4/0/physics_layer_0/angular_velocity = 0.0 -44:4/0 = 0 -44:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:4/0/physics_layer_0/angular_velocity = 0.0 -45:4/0 = 0 -45:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:4/0/physics_layer_0/angular_velocity = 0.0 -46:4/0 = 0 -46:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:4/0/physics_layer_0/angular_velocity = 0.0 -47:4/0 = 0 -47:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:4/0/physics_layer_0/angular_velocity = 0.0 -48:4/0 = 0 -48:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:4/0/physics_layer_0/angular_velocity = 0.0 -0:5/0 = 0 -0:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:5/0/physics_layer_0/angular_velocity = 0.0 -1:5/0 = 0 -1:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:5/0/physics_layer_0/angular_velocity = 0.0 -2:5/0 = 0 -2:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:5/0/physics_layer_0/angular_velocity = 0.0 -3:5/0 = 0 -3:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:5/0/physics_layer_0/angular_velocity = 0.0 -4:5/0 = 0 -4:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:5/0/physics_layer_0/angular_velocity = 0.0 -5:5/0 = 0 -5:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:5/0/physics_layer_0/angular_velocity = 0.0 -6:5/0 = 0 -6:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:5/0/physics_layer_0/angular_velocity = 0.0 -7:5/0 = 0 -7:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:5/0/physics_layer_0/angular_velocity = 0.0 -8:5/0 = 0 -8:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:5/0/physics_layer_0/angular_velocity = 0.0 -9:5/0 = 0 -9:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:5/0/physics_layer_0/angular_velocity = 0.0 -10:5/0 = 0 -10:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:5/0/physics_layer_0/angular_velocity = 0.0 -11:5/0 = 0 -11:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:5/0/physics_layer_0/angular_velocity = 0.0 -12:5/0 = 0 -12:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:5/0/physics_layer_0/angular_velocity = 0.0 -13:5/0 = 0 -13:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:5/0/physics_layer_0/angular_velocity = 0.0 -14:5/0 = 0 -14:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:5/0/physics_layer_0/angular_velocity = 0.0 -15:5/0 = 0 -15:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:5/0/physics_layer_0/angular_velocity = 0.0 -16:5/0 = 0 -16:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:5/0/physics_layer_0/angular_velocity = 0.0 -17:5/0 = 0 -17:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:5/0/physics_layer_0/angular_velocity = 0.0 -18:5/0 = 0 -18:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:5/0/physics_layer_0/angular_velocity = 0.0 -19:5/0 = 0 -19:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:5/0/physics_layer_0/angular_velocity = 0.0 -20:5/0 = 0 -20:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:5/0/physics_layer_0/angular_velocity = 0.0 -21:5/0 = 0 -21:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:5/0/physics_layer_0/angular_velocity = 0.0 -22:5/0 = 0 -22:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:5/0/physics_layer_0/angular_velocity = 0.0 -23:5/0 = 0 -23:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:5/0/physics_layer_0/angular_velocity = 0.0 -24:5/0 = 0 -24:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:5/0/physics_layer_0/angular_velocity = 0.0 -25:5/0 = 0 -25:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:5/0/physics_layer_0/angular_velocity = 0.0 -26:5/0 = 0 -26:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:5/0/physics_layer_0/angular_velocity = 0.0 -27:5/0 = 0 -27:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:5/0/physics_layer_0/angular_velocity = 0.0 -28:5/0 = 0 -28:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:5/0/physics_layer_0/angular_velocity = 0.0 -29:5/0 = 0 -29:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:5/0/physics_layer_0/angular_velocity = 0.0 -30:5/0 = 0 -30:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:5/0/physics_layer_0/angular_velocity = 0.0 -31:5/0 = 0 -31:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:5/0/physics_layer_0/angular_velocity = 0.0 -32:5/0 = 0 -32:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:5/0/physics_layer_0/angular_velocity = 0.0 -33:5/0 = 0 -33:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:5/0/physics_layer_0/angular_velocity = 0.0 -34:5/0 = 0 -34:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:5/0/physics_layer_0/angular_velocity = 0.0 -35:5/0 = 0 -35:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:5/0/physics_layer_0/angular_velocity = 0.0 -36:5/0 = 0 -36:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:5/0/physics_layer_0/angular_velocity = 0.0 -37:5/0 = 0 -37:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:5/0/physics_layer_0/angular_velocity = 0.0 -38:5/0 = 0 -38:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:5/0/physics_layer_0/angular_velocity = 0.0 -39:5/0 = 0 -39:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:5/0/physics_layer_0/angular_velocity = 0.0 -40:5/0 = 0 -40:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:5/0/physics_layer_0/angular_velocity = 0.0 -41:5/0 = 0 -41:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:5/0/physics_layer_0/angular_velocity = 0.0 -42:5/0 = 0 -42:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:5/0/physics_layer_0/angular_velocity = 0.0 -43:5/0 = 0 -43:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:5/0/physics_layer_0/angular_velocity = 0.0 -44:5/0 = 0 -44:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:5/0/physics_layer_0/angular_velocity = 0.0 -45:5/0 = 0 -45:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:5/0/physics_layer_0/angular_velocity = 0.0 -46:5/0 = 0 -46:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:5/0/physics_layer_0/angular_velocity = 0.0 -47:5/0 = 0 -47:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:5/0/physics_layer_0/angular_velocity = 0.0 -48:5/0 = 0 -48:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:5/0/physics_layer_0/angular_velocity = 0.0 -0:6/0 = 0 -0:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:6/0/physics_layer_0/angular_velocity = 0.0 -1:6/0 = 0 -1:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:6/0/physics_layer_0/angular_velocity = 0.0 -2:6/0 = 0 -2:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:6/0/physics_layer_0/angular_velocity = 0.0 -3:6/0 = 0 -3:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:6/0/physics_layer_0/angular_velocity = 0.0 -4:6/0 = 0 -4:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:6/0/physics_layer_0/angular_velocity = 0.0 -5:6/0 = 0 -5:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:6/0/physics_layer_0/angular_velocity = 0.0 -6:6/0 = 0 -6:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:6/0/physics_layer_0/angular_velocity = 0.0 -7:6/0 = 0 -7:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:6/0/physics_layer_0/angular_velocity = 0.0 -8:6/0 = 0 -8:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:6/0/physics_layer_0/angular_velocity = 0.0 -9:6/0 = 0 -9:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:6/0/physics_layer_0/angular_velocity = 0.0 -10:6/0 = 0 -10:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:6/0/physics_layer_0/angular_velocity = 0.0 -11:6/0 = 0 -11:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:6/0/physics_layer_0/angular_velocity = 0.0 -12:6/0 = 0 -12:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:6/0/physics_layer_0/angular_velocity = 0.0 -13:6/0 = 0 -13:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:6/0/physics_layer_0/angular_velocity = 0.0 -14:6/0 = 0 -14:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:6/0/physics_layer_0/angular_velocity = 0.0 -15:6/0 = 0 -15:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:6/0/physics_layer_0/angular_velocity = 0.0 -16:6/0 = 0 -16:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:6/0/physics_layer_0/angular_velocity = 0.0 -17:6/0 = 0 -17:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:6/0/physics_layer_0/angular_velocity = 0.0 -18:6/0 = 0 -18:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:6/0/physics_layer_0/angular_velocity = 0.0 -19:6/0 = 0 -19:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:6/0/physics_layer_0/angular_velocity = 0.0 -20:6/0 = 0 -20:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:6/0/physics_layer_0/angular_velocity = 0.0 -21:6/0 = 0 -21:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:6/0/physics_layer_0/angular_velocity = 0.0 -22:6/0 = 0 -22:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:6/0/physics_layer_0/angular_velocity = 0.0 -23:6/0 = 0 -23:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:6/0/physics_layer_0/angular_velocity = 0.0 -24:6/0 = 0 -24:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:6/0/physics_layer_0/angular_velocity = 0.0 -25:6/0 = 0 -25:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:6/0/physics_layer_0/angular_velocity = 0.0 -26:6/0 = 0 -26:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:6/0/physics_layer_0/angular_velocity = 0.0 -27:6/0 = 0 -27:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:6/0/physics_layer_0/angular_velocity = 0.0 -28:6/0 = 0 -28:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:6/0/physics_layer_0/angular_velocity = 0.0 -29:6/0 = 0 -29:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:6/0/physics_layer_0/angular_velocity = 0.0 -30:6/0 = 0 -30:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:6/0/physics_layer_0/angular_velocity = 0.0 -31:6/0 = 0 -31:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:6/0/physics_layer_0/angular_velocity = 0.0 -32:6/0 = 0 -32:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:6/0/physics_layer_0/angular_velocity = 0.0 -33:6/0 = 0 -33:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:6/0/physics_layer_0/angular_velocity = 0.0 -34:6/0 = 0 -34:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:6/0/physics_layer_0/angular_velocity = 0.0 -35:6/0 = 0 -35:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:6/0/physics_layer_0/angular_velocity = 0.0 -36:6/0 = 0 -36:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:6/0/physics_layer_0/angular_velocity = 0.0 -37:6/0 = 0 -37:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:6/0/physics_layer_0/angular_velocity = 0.0 -38:6/0 = 0 -38:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:6/0/physics_layer_0/angular_velocity = 0.0 -39:6/0 = 0 -39:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:6/0/physics_layer_0/angular_velocity = 0.0 -40:6/0 = 0 -40:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:6/0/physics_layer_0/angular_velocity = 0.0 -41:6/0 = 0 -41:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:6/0/physics_layer_0/angular_velocity = 0.0 -42:6/0 = 0 -42:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:6/0/physics_layer_0/angular_velocity = 0.0 -43:6/0 = 0 -43:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:6/0/physics_layer_0/angular_velocity = 0.0 -44:6/0 = 0 -44:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:6/0/physics_layer_0/angular_velocity = 0.0 -45:6/0 = 0 -45:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:6/0/physics_layer_0/angular_velocity = 0.0 -46:6/0 = 0 -46:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:6/0/physics_layer_0/angular_velocity = 0.0 -47:6/0 = 0 -47:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:6/0/physics_layer_0/angular_velocity = 0.0 -48:6/0 = 0 -48:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:6/0/physics_layer_0/angular_velocity = 0.0 -0:7/0 = 0 -0:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:7/0/physics_layer_0/angular_velocity = 0.0 -1:7/0 = 0 -1:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:7/0/physics_layer_0/angular_velocity = 0.0 -2:7/0 = 0 -2:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:7/0/physics_layer_0/angular_velocity = 0.0 -3:7/0 = 0 -3:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:7/0/physics_layer_0/angular_velocity = 0.0 -4:7/0 = 0 -4:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:7/0/physics_layer_0/angular_velocity = 0.0 -5:7/0 = 0 -5:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:7/0/physics_layer_0/angular_velocity = 0.0 -6:7/0 = 0 -6:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:7/0/physics_layer_0/angular_velocity = 0.0 -7:7/0 = 0 -7:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:7/0/physics_layer_0/angular_velocity = 0.0 -8:7/0 = 0 -8:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:7/0/physics_layer_0/angular_velocity = 0.0 -9:7/0 = 0 -9:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:7/0/physics_layer_0/angular_velocity = 0.0 -10:7/0 = 0 -10:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:7/0/physics_layer_0/angular_velocity = 0.0 -11:7/0 = 0 -11:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:7/0/physics_layer_0/angular_velocity = 0.0 -12:7/0 = 0 -12:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:7/0/physics_layer_0/angular_velocity = 0.0 -13:7/0 = 0 -13:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:7/0/physics_layer_0/angular_velocity = 0.0 -14:7/0 = 0 -14:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:7/0/physics_layer_0/angular_velocity = 0.0 -15:7/0 = 0 -15:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:7/0/physics_layer_0/angular_velocity = 0.0 -16:7/0 = 0 -16:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:7/0/physics_layer_0/angular_velocity = 0.0 -17:7/0 = 0 -17:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:7/0/physics_layer_0/angular_velocity = 0.0 -18:7/0 = 0 -18:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:7/0/physics_layer_0/angular_velocity = 0.0 -19:7/0 = 0 -19:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:7/0/physics_layer_0/angular_velocity = 0.0 -20:7/0 = 0 -20:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:7/0/physics_layer_0/angular_velocity = 0.0 -21:7/0 = 0 -21:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:7/0/physics_layer_0/angular_velocity = 0.0 -22:7/0 = 0 -22:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:7/0/physics_layer_0/angular_velocity = 0.0 -23:7/0 = 0 -23:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:7/0/physics_layer_0/angular_velocity = 0.0 -24:7/0 = 0 -24:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:7/0/physics_layer_0/angular_velocity = 0.0 -25:7/0 = 0 -25:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:7/0/physics_layer_0/angular_velocity = 0.0 -26:7/0 = 0 -26:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:7/0/physics_layer_0/angular_velocity = 0.0 -27:7/0 = 0 -27:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:7/0/physics_layer_0/angular_velocity = 0.0 -28:7/0 = 0 -28:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:7/0/physics_layer_0/angular_velocity = 0.0 -29:7/0 = 0 -29:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:7/0/physics_layer_0/angular_velocity = 0.0 -30:7/0 = 0 -30:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:7/0/physics_layer_0/angular_velocity = 0.0 -31:7/0 = 0 -31:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:7/0/physics_layer_0/angular_velocity = 0.0 -32:7/0 = 0 -32:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:7/0/physics_layer_0/angular_velocity = 0.0 -33:7/0 = 0 -33:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:7/0/physics_layer_0/angular_velocity = 0.0 -34:7/0 = 0 -34:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:7/0/physics_layer_0/angular_velocity = 0.0 -35:7/0 = 0 -35:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:7/0/physics_layer_0/angular_velocity = 0.0 -36:7/0 = 0 -36:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:7/0/physics_layer_0/angular_velocity = 0.0 -37:7/0 = 0 -37:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:7/0/physics_layer_0/angular_velocity = 0.0 -38:7/0 = 0 -38:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:7/0/physics_layer_0/angular_velocity = 0.0 -39:7/0 = 0 -39:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:7/0/physics_layer_0/angular_velocity = 0.0 -40:7/0 = 0 -40:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:7/0/physics_layer_0/angular_velocity = 0.0 -41:7/0 = 0 -41:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:7/0/physics_layer_0/angular_velocity = 0.0 -42:7/0 = 0 -42:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:7/0/physics_layer_0/angular_velocity = 0.0 -43:7/0 = 0 -43:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:7/0/physics_layer_0/angular_velocity = 0.0 -44:7/0 = 0 -44:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:7/0/physics_layer_0/angular_velocity = 0.0 -45:7/0 = 0 -45:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:7/0/physics_layer_0/angular_velocity = 0.0 -46:7/0 = 0 -46:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:7/0/physics_layer_0/angular_velocity = 0.0 -47:7/0 = 0 -47:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:7/0/physics_layer_0/angular_velocity = 0.0 -48:7/0 = 0 -48:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:7/0/physics_layer_0/angular_velocity = 0.0 -0:8/0 = 0 -0:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:8/0/physics_layer_0/angular_velocity = 0.0 -1:8/0 = 0 -1:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:8/0/physics_layer_0/angular_velocity = 0.0 -2:8/0 = 0 -2:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:8/0/physics_layer_0/angular_velocity = 0.0 -3:8/0 = 0 -3:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:8/0/physics_layer_0/angular_velocity = 0.0 -4:8/0 = 0 -4:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:8/0/physics_layer_0/angular_velocity = 0.0 -5:8/0 = 0 -5:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:8/0/physics_layer_0/angular_velocity = 0.0 -6:8/0 = 0 -6:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:8/0/physics_layer_0/angular_velocity = 0.0 -7:8/0 = 0 -7:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:8/0/physics_layer_0/angular_velocity = 0.0 -8:8/0 = 0 -8:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:8/0/physics_layer_0/angular_velocity = 0.0 -9:8/0 = 0 -9:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:8/0/physics_layer_0/angular_velocity = 0.0 -10:8/0 = 0 -10:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:8/0/physics_layer_0/angular_velocity = 0.0 -11:8/0 = 0 -11:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:8/0/physics_layer_0/angular_velocity = 0.0 -12:8/0 = 0 -12:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:8/0/physics_layer_0/angular_velocity = 0.0 -13:8/0 = 0 -13:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:8/0/physics_layer_0/angular_velocity = 0.0 -14:8/0 = 0 -14:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:8/0/physics_layer_0/angular_velocity = 0.0 -15:8/0 = 0 -15:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:8/0/physics_layer_0/angular_velocity = 0.0 -16:8/0 = 0 -16:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:8/0/physics_layer_0/angular_velocity = 0.0 -17:8/0 = 0 -17:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:8/0/physics_layer_0/angular_velocity = 0.0 -18:8/0 = 0 -18:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:8/0/physics_layer_0/angular_velocity = 0.0 -19:8/0 = 0 -19:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:8/0/physics_layer_0/angular_velocity = 0.0 -20:8/0 = 0 -20:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:8/0/physics_layer_0/angular_velocity = 0.0 -21:8/0 = 0 -21:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:8/0/physics_layer_0/angular_velocity = 0.0 -22:8/0 = 0 -22:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:8/0/physics_layer_0/angular_velocity = 0.0 -23:8/0 = 0 -23:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:8/0/physics_layer_0/angular_velocity = 0.0 -24:8/0 = 0 -24:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:8/0/physics_layer_0/angular_velocity = 0.0 -25:8/0 = 0 -25:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:8/0/physics_layer_0/angular_velocity = 0.0 -26:8/0 = 0 -26:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:8/0/physics_layer_0/angular_velocity = 0.0 -27:8/0 = 0 -27:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:8/0/physics_layer_0/angular_velocity = 0.0 -28:8/0 = 0 -28:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:8/0/physics_layer_0/angular_velocity = 0.0 -29:8/0 = 0 -29:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:8/0/physics_layer_0/angular_velocity = 0.0 -30:8/0 = 0 -30:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:8/0/physics_layer_0/angular_velocity = 0.0 -31:8/0 = 0 -31:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:8/0/physics_layer_0/angular_velocity = 0.0 -32:8/0 = 0 -32:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:8/0/physics_layer_0/angular_velocity = 0.0 -33:8/0 = 0 -33:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:8/0/physics_layer_0/angular_velocity = 0.0 -34:8/0 = 0 -34:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:8/0/physics_layer_0/angular_velocity = 0.0 -35:8/0 = 0 -35:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:8/0/physics_layer_0/angular_velocity = 0.0 -36:8/0 = 0 -36:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:8/0/physics_layer_0/angular_velocity = 0.0 -37:8/0 = 0 -37:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:8/0/physics_layer_0/angular_velocity = 0.0 -38:8/0 = 0 -38:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:8/0/physics_layer_0/angular_velocity = 0.0 -39:8/0 = 0 -39:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:8/0/physics_layer_0/angular_velocity = 0.0 -40:8/0 = 0 -40:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:8/0/physics_layer_0/angular_velocity = 0.0 -41:8/0 = 0 -41:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:8/0/physics_layer_0/angular_velocity = 0.0 -42:8/0 = 0 -42:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:8/0/physics_layer_0/angular_velocity = 0.0 -43:8/0 = 0 -43:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:8/0/physics_layer_0/angular_velocity = 0.0 -44:8/0 = 0 -44:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:8/0/physics_layer_0/angular_velocity = 0.0 -45:8/0 = 0 -45:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:8/0/physics_layer_0/angular_velocity = 0.0 -46:8/0 = 0 -46:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:8/0/physics_layer_0/angular_velocity = 0.0 -47:8/0 = 0 -47:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:8/0/physics_layer_0/angular_velocity = 0.0 -48:8/0 = 0 -48:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:8/0/physics_layer_0/angular_velocity = 0.0 -0:9/0 = 0 -0:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:9/0/physics_layer_0/angular_velocity = 0.0 -1:9/0 = 0 -1:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:9/0/physics_layer_0/angular_velocity = 0.0 -2:9/0 = 0 -2:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:9/0/physics_layer_0/angular_velocity = 0.0 -3:9/0 = 0 -3:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:9/0/physics_layer_0/angular_velocity = 0.0 -4:9/0 = 0 -4:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:9/0/physics_layer_0/angular_velocity = 0.0 -5:9/0 = 0 -5:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:9/0/physics_layer_0/angular_velocity = 0.0 -6:9/0 = 0 -6:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:9/0/physics_layer_0/angular_velocity = 0.0 -7:9/0 = 0 -7:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:9/0/physics_layer_0/angular_velocity = 0.0 -8:9/0 = 0 -8:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:9/0/physics_layer_0/angular_velocity = 0.0 -9:9/0 = 0 -9:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:9/0/physics_layer_0/angular_velocity = 0.0 -10:9/0 = 0 -10:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:9/0/physics_layer_0/angular_velocity = 0.0 -11:9/0 = 0 -11:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:9/0/physics_layer_0/angular_velocity = 0.0 -12:9/0 = 0 -12:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:9/0/physics_layer_0/angular_velocity = 0.0 -13:9/0 = 0 -13:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:9/0/physics_layer_0/angular_velocity = 0.0 -14:9/0 = 0 -14:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:9/0/physics_layer_0/angular_velocity = 0.0 -15:9/0 = 0 -15:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:9/0/physics_layer_0/angular_velocity = 0.0 -16:9/0 = 0 -16:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:9/0/physics_layer_0/angular_velocity = 0.0 -17:9/0 = 0 -17:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:9/0/physics_layer_0/angular_velocity = 0.0 -18:9/0 = 0 -18:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:9/0/physics_layer_0/angular_velocity = 0.0 -19:9/0 = 0 -19:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:9/0/physics_layer_0/angular_velocity = 0.0 -20:9/0 = 0 -20:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:9/0/physics_layer_0/angular_velocity = 0.0 -21:9/0 = 0 -21:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:9/0/physics_layer_0/angular_velocity = 0.0 -22:9/0 = 0 -22:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:9/0/physics_layer_0/angular_velocity = 0.0 -23:9/0 = 0 -23:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:9/0/physics_layer_0/angular_velocity = 0.0 -24:9/0 = 0 -24:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:9/0/physics_layer_0/angular_velocity = 0.0 -25:9/0 = 0 -25:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:9/0/physics_layer_0/angular_velocity = 0.0 -26:9/0 = 0 -26:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:9/0/physics_layer_0/angular_velocity = 0.0 -27:9/0 = 0 -27:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:9/0/physics_layer_0/angular_velocity = 0.0 -28:9/0 = 0 -28:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:9/0/physics_layer_0/angular_velocity = 0.0 -29:9/0 = 0 -29:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:9/0/physics_layer_0/angular_velocity = 0.0 -30:9/0 = 0 -30:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:9/0/physics_layer_0/angular_velocity = 0.0 -31:9/0 = 0 -31:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:9/0/physics_layer_0/angular_velocity = 0.0 -32:9/0 = 0 -32:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:9/0/physics_layer_0/angular_velocity = 0.0 -33:9/0 = 0 -33:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:9/0/physics_layer_0/angular_velocity = 0.0 -34:9/0 = 0 -34:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:9/0/physics_layer_0/angular_velocity = 0.0 -35:9/0 = 0 -35:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:9/0/physics_layer_0/angular_velocity = 0.0 -36:9/0 = 0 -36:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:9/0/physics_layer_0/angular_velocity = 0.0 -37:9/0 = 0 -37:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:9/0/physics_layer_0/angular_velocity = 0.0 -38:9/0 = 0 -38:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:9/0/physics_layer_0/angular_velocity = 0.0 -39:9/0 = 0 -39:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:9/0/physics_layer_0/angular_velocity = 0.0 -40:9/0 = 0 -40:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:9/0/physics_layer_0/angular_velocity = 0.0 -41:9/0 = 0 -41:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:9/0/physics_layer_0/angular_velocity = 0.0 -42:9/0 = 0 -42:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:9/0/physics_layer_0/angular_velocity = 0.0 -43:9/0 = 0 -43:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:9/0/physics_layer_0/angular_velocity = 0.0 -44:9/0 = 0 -44:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:9/0/physics_layer_0/angular_velocity = 0.0 -45:9/0 = 0 -45:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:9/0/physics_layer_0/angular_velocity = 0.0 -46:9/0 = 0 -46:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:9/0/physics_layer_0/angular_velocity = 0.0 -47:9/0 = 0 -47:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:9/0/physics_layer_0/angular_velocity = 0.0 -48:9/0 = 0 -48:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:9/0/physics_layer_0/angular_velocity = 0.0 -0:10/0 = 0 -0:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:10/0/physics_layer_0/angular_velocity = 0.0 -1:10/0 = 0 -1:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:10/0/physics_layer_0/angular_velocity = 0.0 -2:10/0 = 0 -2:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:10/0/physics_layer_0/angular_velocity = 0.0 -3:10/0 = 0 -3:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:10/0/physics_layer_0/angular_velocity = 0.0 -4:10/0 = 0 -4:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:10/0/physics_layer_0/angular_velocity = 0.0 -5:10/0 = 0 -5:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:10/0/physics_layer_0/angular_velocity = 0.0 -6:10/0 = 0 -6:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:10/0/physics_layer_0/angular_velocity = 0.0 -7:10/0 = 0 -7:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:10/0/physics_layer_0/angular_velocity = 0.0 -8:10/0 = 0 -8:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:10/0/physics_layer_0/angular_velocity = 0.0 -9:10/0 = 0 -9:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:10/0/physics_layer_0/angular_velocity = 0.0 -10:10/0 = 0 -10:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:10/0/physics_layer_0/angular_velocity = 0.0 -11:10/0 = 0 -11:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:10/0/physics_layer_0/angular_velocity = 0.0 -12:10/0 = 0 -12:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:10/0/physics_layer_0/angular_velocity = 0.0 -13:10/0 = 0 -13:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:10/0/physics_layer_0/angular_velocity = 0.0 -14:10/0 = 0 -14:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:10/0/physics_layer_0/angular_velocity = 0.0 -15:10/0 = 0 -15:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:10/0/physics_layer_0/angular_velocity = 0.0 -16:10/0 = 0 -16:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:10/0/physics_layer_0/angular_velocity = 0.0 -17:10/0 = 0 -17:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:10/0/physics_layer_0/angular_velocity = 0.0 -18:10/0 = 0 -18:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:10/0/physics_layer_0/angular_velocity = 0.0 -19:10/0 = 0 -19:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:10/0/physics_layer_0/angular_velocity = 0.0 -20:10/0 = 0 -20:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:10/0/physics_layer_0/angular_velocity = 0.0 -21:10/0 = 0 -21:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:10/0/physics_layer_0/angular_velocity = 0.0 -22:10/0 = 0 -22:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:10/0/physics_layer_0/angular_velocity = 0.0 -23:10/0 = 0 -23:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:10/0/physics_layer_0/angular_velocity = 0.0 -24:10/0 = 0 -24:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:10/0/physics_layer_0/angular_velocity = 0.0 -25:10/0 = 0 -25:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:10/0/physics_layer_0/angular_velocity = 0.0 -26:10/0 = 0 -26:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:10/0/physics_layer_0/angular_velocity = 0.0 -27:10/0 = 0 -27:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:10/0/physics_layer_0/angular_velocity = 0.0 -28:10/0 = 0 -28:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:10/0/physics_layer_0/angular_velocity = 0.0 -29:10/0 = 0 -29:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:10/0/physics_layer_0/angular_velocity = 0.0 -30:10/0 = 0 -30:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:10/0/physics_layer_0/angular_velocity = 0.0 -31:10/0 = 0 -31:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:10/0/physics_layer_0/angular_velocity = 0.0 -32:10/0 = 0 -32:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:10/0/physics_layer_0/angular_velocity = 0.0 -33:10/0 = 0 -33:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:10/0/physics_layer_0/angular_velocity = 0.0 -34:10/0 = 0 -34:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:10/0/physics_layer_0/angular_velocity = 0.0 -35:10/0 = 0 -35:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:10/0/physics_layer_0/angular_velocity = 0.0 -36:10/0 = 0 -36:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:10/0/physics_layer_0/angular_velocity = 0.0 -37:10/0 = 0 -37:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:10/0/physics_layer_0/angular_velocity = 0.0 -38:10/0 = 0 -38:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:10/0/physics_layer_0/angular_velocity = 0.0 -39:10/0 = 0 -39:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:10/0/physics_layer_0/angular_velocity = 0.0 -40:10/0 = 0 -40:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:10/0/physics_layer_0/angular_velocity = 0.0 -41:10/0 = 0 -41:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:10/0/physics_layer_0/angular_velocity = 0.0 -42:10/0 = 0 -42:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:10/0/physics_layer_0/angular_velocity = 0.0 -43:10/0 = 0 -43:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:10/0/physics_layer_0/angular_velocity = 0.0 -44:10/0 = 0 -44:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:10/0/physics_layer_0/angular_velocity = 0.0 -45:10/0 = 0 -45:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:10/0/physics_layer_0/angular_velocity = 0.0 -46:10/0 = 0 -46:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:10/0/physics_layer_0/angular_velocity = 0.0 -47:10/0 = 0 -47:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:10/0/physics_layer_0/angular_velocity = 0.0 -48:10/0 = 0 -48:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:10/0/physics_layer_0/angular_velocity = 0.0 -0:11/0 = 0 -0:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:11/0/physics_layer_0/angular_velocity = 0.0 -1:11/0 = 0 -1:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:11/0/physics_layer_0/angular_velocity = 0.0 -2:11/0 = 0 -2:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:11/0/physics_layer_0/angular_velocity = 0.0 -3:11/0 = 0 -3:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:11/0/physics_layer_0/angular_velocity = 0.0 -4:11/0 = 0 -4:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:11/0/physics_layer_0/angular_velocity = 0.0 -5:11/0 = 0 -5:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:11/0/physics_layer_0/angular_velocity = 0.0 -6:11/0 = 0 -6:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:11/0/physics_layer_0/angular_velocity = 0.0 -7:11/0 = 0 -7:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:11/0/physics_layer_0/angular_velocity = 0.0 -8:11/0 = 0 -8:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:11/0/physics_layer_0/angular_velocity = 0.0 -9:11/0 = 0 -9:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:11/0/physics_layer_0/angular_velocity = 0.0 -10:11/0 = 0 -10:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:11/0/physics_layer_0/angular_velocity = 0.0 -11:11/0 = 0 -11:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:11/0/physics_layer_0/angular_velocity = 0.0 -12:11/0 = 0 -12:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:11/0/physics_layer_0/angular_velocity = 0.0 -13:11/0 = 0 -13:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:11/0/physics_layer_0/angular_velocity = 0.0 -14:11/0 = 0 -14:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:11/0/physics_layer_0/angular_velocity = 0.0 -15:11/0 = 0 -15:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:11/0/physics_layer_0/angular_velocity = 0.0 -16:11/0 = 0 -16:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:11/0/physics_layer_0/angular_velocity = 0.0 -17:11/0 = 0 -17:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:11/0/physics_layer_0/angular_velocity = 0.0 -18:11/0 = 0 -18:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:11/0/physics_layer_0/angular_velocity = 0.0 -19:11/0 = 0 -19:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:11/0/physics_layer_0/angular_velocity = 0.0 -20:11/0 = 0 -20:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:11/0/physics_layer_0/angular_velocity = 0.0 -21:11/0 = 0 -21:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:11/0/physics_layer_0/angular_velocity = 0.0 -22:11/0 = 0 -22:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:11/0/physics_layer_0/angular_velocity = 0.0 -23:11/0 = 0 -23:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:11/0/physics_layer_0/angular_velocity = 0.0 -24:11/0 = 0 -24:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:11/0/physics_layer_0/angular_velocity = 0.0 -25:11/0 = 0 -25:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:11/0/physics_layer_0/angular_velocity = 0.0 -26:11/0 = 0 -26:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:11/0/physics_layer_0/angular_velocity = 0.0 -27:11/0 = 0 -27:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:11/0/physics_layer_0/angular_velocity = 0.0 -28:11/0 = 0 -28:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:11/0/physics_layer_0/angular_velocity = 0.0 -29:11/0 = 0 -29:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:11/0/physics_layer_0/angular_velocity = 0.0 -30:11/0 = 0 -30:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:11/0/physics_layer_0/angular_velocity = 0.0 -31:11/0 = 0 -31:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:11/0/physics_layer_0/angular_velocity = 0.0 -32:11/0 = 0 -32:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:11/0/physics_layer_0/angular_velocity = 0.0 -33:11/0 = 0 -33:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:11/0/physics_layer_0/angular_velocity = 0.0 -34:11/0 = 0 -34:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:11/0/physics_layer_0/angular_velocity = 0.0 -35:11/0 = 0 -35:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:11/0/physics_layer_0/angular_velocity = 0.0 -36:11/0 = 0 -36:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:11/0/physics_layer_0/angular_velocity = 0.0 -37:11/0 = 0 -37:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:11/0/physics_layer_0/angular_velocity = 0.0 -38:11/0 = 0 -38:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:11/0/physics_layer_0/angular_velocity = 0.0 -39:11/0 = 0 -39:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:11/0/physics_layer_0/angular_velocity = 0.0 -40:11/0 = 0 -40:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:11/0/physics_layer_0/angular_velocity = 0.0 -41:11/0 = 0 -41:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:11/0/physics_layer_0/angular_velocity = 0.0 -42:11/0 = 0 -42:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:11/0/physics_layer_0/angular_velocity = 0.0 -43:11/0 = 0 -43:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:11/0/physics_layer_0/angular_velocity = 0.0 -44:11/0 = 0 -44:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:11/0/physics_layer_0/angular_velocity = 0.0 -45:11/0 = 0 -45:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:11/0/physics_layer_0/angular_velocity = 0.0 -46:11/0 = 0 -46:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:11/0/physics_layer_0/angular_velocity = 0.0 -47:11/0 = 0 -47:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:11/0/physics_layer_0/angular_velocity = 0.0 -48:11/0 = 0 -48:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:11/0/physics_layer_0/angular_velocity = 0.0 -0:12/0 = 0 -0:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:12/0/physics_layer_0/angular_velocity = 0.0 -1:12/0 = 0 -1:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:12/0/physics_layer_0/angular_velocity = 0.0 -2:12/0 = 0 -2:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:12/0/physics_layer_0/angular_velocity = 0.0 -3:12/0 = 0 -3:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:12/0/physics_layer_0/angular_velocity = 0.0 -4:12/0 = 0 -4:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:12/0/physics_layer_0/angular_velocity = 0.0 -5:12/0 = 0 -5:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:12/0/physics_layer_0/angular_velocity = 0.0 -6:12/0 = 0 -6:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:12/0/physics_layer_0/angular_velocity = 0.0 -7:12/0 = 0 -7:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:12/0/physics_layer_0/angular_velocity = 0.0 -8:12/0 = 0 -8:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:12/0/physics_layer_0/angular_velocity = 0.0 -9:12/0 = 0 -9:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:12/0/physics_layer_0/angular_velocity = 0.0 -10:12/0 = 0 -10:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:12/0/physics_layer_0/angular_velocity = 0.0 -11:12/0 = 0 -11:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:12/0/physics_layer_0/angular_velocity = 0.0 -12:12/0 = 0 -12:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:12/0/physics_layer_0/angular_velocity = 0.0 -13:12/0 = 0 -13:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:12/0/physics_layer_0/angular_velocity = 0.0 -14:12/0 = 0 -14:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:12/0/physics_layer_0/angular_velocity = 0.0 -15:12/0 = 0 -15:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:12/0/physics_layer_0/angular_velocity = 0.0 -16:12/0 = 0 -16:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:12/0/physics_layer_0/angular_velocity = 0.0 -17:12/0 = 0 -17:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:12/0/physics_layer_0/angular_velocity = 0.0 -18:12/0 = 0 -18:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:12/0/physics_layer_0/angular_velocity = 0.0 -19:12/0 = 0 -19:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:12/0/physics_layer_0/angular_velocity = 0.0 -20:12/0 = 0 -20:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:12/0/physics_layer_0/angular_velocity = 0.0 -21:12/0 = 0 -21:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:12/0/physics_layer_0/angular_velocity = 0.0 -22:12/0 = 0 -22:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:12/0/physics_layer_0/angular_velocity = 0.0 -23:12/0 = 0 -23:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:12/0/physics_layer_0/angular_velocity = 0.0 -24:12/0 = 0 -24:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:12/0/physics_layer_0/angular_velocity = 0.0 -25:12/0 = 0 -25:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:12/0/physics_layer_0/angular_velocity = 0.0 -26:12/0 = 0 -26:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:12/0/physics_layer_0/angular_velocity = 0.0 -27:12/0 = 0 -27:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:12/0/physics_layer_0/angular_velocity = 0.0 -28:12/0 = 0 -28:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:12/0/physics_layer_0/angular_velocity = 0.0 -29:12/0 = 0 -29:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:12/0/physics_layer_0/angular_velocity = 0.0 -30:12/0 = 0 -30:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:12/0/physics_layer_0/angular_velocity = 0.0 -31:12/0 = 0 -31:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:12/0/physics_layer_0/angular_velocity = 0.0 -32:12/0 = 0 -32:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:12/0/physics_layer_0/angular_velocity = 0.0 -33:12/0 = 0 -33:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:12/0/physics_layer_0/angular_velocity = 0.0 -34:12/0 = 0 -34:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:12/0/physics_layer_0/angular_velocity = 0.0 -35:12/0 = 0 -35:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:12/0/physics_layer_0/angular_velocity = 0.0 -36:12/0 = 0 -36:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:12/0/physics_layer_0/angular_velocity = 0.0 -37:12/0 = 0 -37:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:12/0/physics_layer_0/angular_velocity = 0.0 -38:12/0 = 0 -38:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:12/0/physics_layer_0/angular_velocity = 0.0 -39:12/0 = 0 -39:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:12/0/physics_layer_0/angular_velocity = 0.0 -40:12/0 = 0 -40:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:12/0/physics_layer_0/angular_velocity = 0.0 -41:12/0 = 0 -41:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:12/0/physics_layer_0/angular_velocity = 0.0 -42:12/0 = 0 -42:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:12/0/physics_layer_0/angular_velocity = 0.0 -43:12/0 = 0 -43:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:12/0/physics_layer_0/angular_velocity = 0.0 -44:12/0 = 0 -44:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:12/0/physics_layer_0/angular_velocity = 0.0 -45:12/0 = 0 -45:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:12/0/physics_layer_0/angular_velocity = 0.0 -46:12/0 = 0 -46:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:12/0/physics_layer_0/angular_velocity = 0.0 -47:12/0 = 0 -47:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:12/0/physics_layer_0/angular_velocity = 0.0 -48:12/0 = 0 -48:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:12/0/physics_layer_0/angular_velocity = 0.0 -0:13/0 = 0 -0:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:13/0/physics_layer_0/angular_velocity = 0.0 -1:13/0 = 0 -1:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:13/0/physics_layer_0/angular_velocity = 0.0 -2:13/0 = 0 -2:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:13/0/physics_layer_0/angular_velocity = 0.0 -3:13/0 = 0 -3:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:13/0/physics_layer_0/angular_velocity = 0.0 -4:13/0 = 0 -4:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:13/0/physics_layer_0/angular_velocity = 0.0 -5:13/0 = 0 -5:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:13/0/physics_layer_0/angular_velocity = 0.0 -6:13/0 = 0 -6:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:13/0/physics_layer_0/angular_velocity = 0.0 -7:13/0 = 0 -7:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:13/0/physics_layer_0/angular_velocity = 0.0 -8:13/0 = 0 -8:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:13/0/physics_layer_0/angular_velocity = 0.0 -9:13/0 = 0 -9:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:13/0/physics_layer_0/angular_velocity = 0.0 -10:13/0 = 0 -10:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:13/0/physics_layer_0/angular_velocity = 0.0 -11:13/0 = 0 -11:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:13/0/physics_layer_0/angular_velocity = 0.0 -12:13/0 = 0 -12:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:13/0/physics_layer_0/angular_velocity = 0.0 -13:13/0 = 0 -13:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:13/0/physics_layer_0/angular_velocity = 0.0 -14:13/0 = 0 -14:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:13/0/physics_layer_0/angular_velocity = 0.0 -15:13/0 = 0 -15:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:13/0/physics_layer_0/angular_velocity = 0.0 -16:13/0 = 0 -16:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:13/0/physics_layer_0/angular_velocity = 0.0 -17:13/0 = 0 -17:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:13/0/physics_layer_0/angular_velocity = 0.0 -18:13/0 = 0 -18:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:13/0/physics_layer_0/angular_velocity = 0.0 -19:13/0 = 0 -19:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:13/0/physics_layer_0/angular_velocity = 0.0 -20:13/0 = 0 -20:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:13/0/physics_layer_0/angular_velocity = 0.0 -21:13/0 = 0 -21:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:13/0/physics_layer_0/angular_velocity = 0.0 -22:13/0 = 0 -22:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:13/0/physics_layer_0/angular_velocity = 0.0 -23:13/0 = 0 -23:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:13/0/physics_layer_0/angular_velocity = 0.0 -24:13/0 = 0 -24:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:13/0/physics_layer_0/angular_velocity = 0.0 -25:13/0 = 0 -25:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:13/0/physics_layer_0/angular_velocity = 0.0 -26:13/0 = 0 -26:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:13/0/physics_layer_0/angular_velocity = 0.0 -27:13/0 = 0 -27:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:13/0/physics_layer_0/angular_velocity = 0.0 -28:13/0 = 0 -28:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:13/0/physics_layer_0/angular_velocity = 0.0 -29:13/0 = 0 -29:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:13/0/physics_layer_0/angular_velocity = 0.0 -30:13/0 = 0 -30:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:13/0/physics_layer_0/angular_velocity = 0.0 -31:13/0 = 0 -31:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:13/0/physics_layer_0/angular_velocity = 0.0 -32:13/0 = 0 -32:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:13/0/physics_layer_0/angular_velocity = 0.0 -33:13/0 = 0 -33:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:13/0/physics_layer_0/angular_velocity = 0.0 -34:13/0 = 0 -34:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:13/0/physics_layer_0/angular_velocity = 0.0 -35:13/0 = 0 -35:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:13/0/physics_layer_0/angular_velocity = 0.0 -36:13/0 = 0 -36:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:13/0/physics_layer_0/angular_velocity = 0.0 -37:13/0 = 0 -37:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:13/0/physics_layer_0/angular_velocity = 0.0 -38:13/0 = 0 -38:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:13/0/physics_layer_0/angular_velocity = 0.0 -39:13/0 = 0 -39:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:13/0/physics_layer_0/angular_velocity = 0.0 -40:13/0 = 0 -40:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:13/0/physics_layer_0/angular_velocity = 0.0 -41:13/0 = 0 -41:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:13/0/physics_layer_0/angular_velocity = 0.0 -42:13/0 = 0 -42:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:13/0/physics_layer_0/angular_velocity = 0.0 -43:13/0 = 0 -43:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:13/0/physics_layer_0/angular_velocity = 0.0 -44:13/0 = 0 -44:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:13/0/physics_layer_0/angular_velocity = 0.0 -45:13/0 = 0 -45:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:13/0/physics_layer_0/angular_velocity = 0.0 -46:13/0 = 0 -46:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:13/0/physics_layer_0/angular_velocity = 0.0 -47:13/0 = 0 -47:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:13/0/physics_layer_0/angular_velocity = 0.0 -48:13/0 = 0 -48:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:13/0/physics_layer_0/angular_velocity = 0.0 -0:14/0 = 0 -0:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:14/0/physics_layer_0/angular_velocity = 0.0 -1:14/0 = 0 -1:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:14/0/physics_layer_0/angular_velocity = 0.0 -2:14/0 = 0 -2:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:14/0/physics_layer_0/angular_velocity = 0.0 -3:14/0 = 0 -3:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:14/0/physics_layer_0/angular_velocity = 0.0 -4:14/0 = 0 -4:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:14/0/physics_layer_0/angular_velocity = 0.0 -5:14/0 = 0 -5:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:14/0/physics_layer_0/angular_velocity = 0.0 -6:14/0 = 0 -6:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:14/0/physics_layer_0/angular_velocity = 0.0 -7:14/0 = 0 -7:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:14/0/physics_layer_0/angular_velocity = 0.0 -8:14/0 = 0 -8:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:14/0/physics_layer_0/angular_velocity = 0.0 -9:14/0 = 0 -9:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:14/0/physics_layer_0/angular_velocity = 0.0 -10:14/0 = 0 -10:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:14/0/physics_layer_0/angular_velocity = 0.0 -11:14/0 = 0 -11:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:14/0/physics_layer_0/angular_velocity = 0.0 -12:14/0 = 0 -12:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:14/0/physics_layer_0/angular_velocity = 0.0 -13:14/0 = 0 -13:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:14/0/physics_layer_0/angular_velocity = 0.0 -14:14/0 = 0 -14:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:14/0/physics_layer_0/angular_velocity = 0.0 -15:14/0 = 0 -15:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:14/0/physics_layer_0/angular_velocity = 0.0 -16:14/0 = 0 -16:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:14/0/physics_layer_0/angular_velocity = 0.0 -17:14/0 = 0 -17:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:14/0/physics_layer_0/angular_velocity = 0.0 -18:14/0 = 0 -18:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:14/0/physics_layer_0/angular_velocity = 0.0 -19:14/0 = 0 -19:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:14/0/physics_layer_0/angular_velocity = 0.0 -20:14/0 = 0 -20:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:14/0/physics_layer_0/angular_velocity = 0.0 -21:14/0 = 0 -21:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:14/0/physics_layer_0/angular_velocity = 0.0 -22:14/0 = 0 -22:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:14/0/physics_layer_0/angular_velocity = 0.0 -23:14/0 = 0 -23:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:14/0/physics_layer_0/angular_velocity = 0.0 -24:14/0 = 0 -24:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:14/0/physics_layer_0/angular_velocity = 0.0 -25:14/0 = 0 -25:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:14/0/physics_layer_0/angular_velocity = 0.0 -26:14/0 = 0 -26:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:14/0/physics_layer_0/angular_velocity = 0.0 -27:14/0 = 0 -27:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:14/0/physics_layer_0/angular_velocity = 0.0 -28:14/0 = 0 -28:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:14/0/physics_layer_0/angular_velocity = 0.0 -29:14/0 = 0 -29:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:14/0/physics_layer_0/angular_velocity = 0.0 -30:14/0 = 0 -30:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:14/0/physics_layer_0/angular_velocity = 0.0 -31:14/0 = 0 -31:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:14/0/physics_layer_0/angular_velocity = 0.0 -32:14/0 = 0 -32:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:14/0/physics_layer_0/angular_velocity = 0.0 -33:14/0 = 0 -33:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:14/0/physics_layer_0/angular_velocity = 0.0 -34:14/0 = 0 -34:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:14/0/physics_layer_0/angular_velocity = 0.0 -35:14/0 = 0 -35:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:14/0/physics_layer_0/angular_velocity = 0.0 -36:14/0 = 0 -36:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:14/0/physics_layer_0/angular_velocity = 0.0 -37:14/0 = 0 -37:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:14/0/physics_layer_0/angular_velocity = 0.0 -38:14/0 = 0 -38:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:14/0/physics_layer_0/angular_velocity = 0.0 -39:14/0 = 0 -39:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:14/0/physics_layer_0/angular_velocity = 0.0 -40:14/0 = 0 -40:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:14/0/physics_layer_0/angular_velocity = 0.0 -41:14/0 = 0 -41:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:14/0/physics_layer_0/angular_velocity = 0.0 -42:14/0 = 0 -42:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:14/0/physics_layer_0/angular_velocity = 0.0 -43:14/0 = 0 -43:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:14/0/physics_layer_0/angular_velocity = 0.0 -44:14/0 = 0 -44:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:14/0/physics_layer_0/angular_velocity = 0.0 -45:14/0 = 0 -45:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:14/0/physics_layer_0/angular_velocity = 0.0 -46:14/0 = 0 -46:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:14/0/physics_layer_0/angular_velocity = 0.0 -47:14/0 = 0 -47:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:14/0/physics_layer_0/angular_velocity = 0.0 -48:14/0 = 0 -48:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:14/0/physics_layer_0/angular_velocity = 0.0 -0:15/0 = 0 -0:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:15/0/physics_layer_0/angular_velocity = 0.0 -1:15/0 = 0 -1:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:15/0/physics_layer_0/angular_velocity = 0.0 -2:15/0 = 0 -2:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:15/0/physics_layer_0/angular_velocity = 0.0 -3:15/0 = 0 -3:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:15/0/physics_layer_0/angular_velocity = 0.0 -4:15/0 = 0 -4:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:15/0/physics_layer_0/angular_velocity = 0.0 -5:15/0 = 0 -5:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:15/0/physics_layer_0/angular_velocity = 0.0 -6:15/0 = 0 -6:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:15/0/physics_layer_0/angular_velocity = 0.0 -7:15/0 = 0 -7:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:15/0/physics_layer_0/angular_velocity = 0.0 -8:15/0 = 0 -8:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:15/0/physics_layer_0/angular_velocity = 0.0 -9:15/0 = 0 -9:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:15/0/physics_layer_0/angular_velocity = 0.0 -10:15/0 = 0 -10:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:15/0/physics_layer_0/angular_velocity = 0.0 -11:15/0 = 0 -11:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:15/0/physics_layer_0/angular_velocity = 0.0 -12:15/0 = 0 -12:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:15/0/physics_layer_0/angular_velocity = 0.0 -13:15/0 = 0 -13:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:15/0/physics_layer_0/angular_velocity = 0.0 -14:15/0 = 0 -14:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:15/0/physics_layer_0/angular_velocity = 0.0 -15:15/0 = 0 -15:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:15/0/physics_layer_0/angular_velocity = 0.0 -16:15/0 = 0 -16:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:15/0/physics_layer_0/angular_velocity = 0.0 -17:15/0 = 0 -17:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:15/0/physics_layer_0/angular_velocity = 0.0 -18:15/0 = 0 -18:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:15/0/physics_layer_0/angular_velocity = 0.0 -19:15/0 = 0 -19:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:15/0/physics_layer_0/angular_velocity = 0.0 -20:15/0 = 0 -20:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:15/0/physics_layer_0/angular_velocity = 0.0 -21:15/0 = 0 -21:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:15/0/physics_layer_0/angular_velocity = 0.0 -22:15/0 = 0 -22:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:15/0/physics_layer_0/angular_velocity = 0.0 -23:15/0 = 0 -23:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:15/0/physics_layer_0/angular_velocity = 0.0 -24:15/0 = 0 -24:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:15/0/physics_layer_0/angular_velocity = 0.0 -25:15/0 = 0 -25:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:15/0/physics_layer_0/angular_velocity = 0.0 -26:15/0 = 0 -26:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:15/0/physics_layer_0/angular_velocity = 0.0 -27:15/0 = 0 -27:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:15/0/physics_layer_0/angular_velocity = 0.0 -28:15/0 = 0 -28:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:15/0/physics_layer_0/angular_velocity = 0.0 -29:15/0 = 0 -29:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:15/0/physics_layer_0/angular_velocity = 0.0 -30:15/0 = 0 -30:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:15/0/physics_layer_0/angular_velocity = 0.0 -31:15/0 = 0 -31:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:15/0/physics_layer_0/angular_velocity = 0.0 -32:15/0 = 0 -32:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:15/0/physics_layer_0/angular_velocity = 0.0 -33:15/0 = 0 -33:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:15/0/physics_layer_0/angular_velocity = 0.0 -34:15/0 = 0 -34:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:15/0/physics_layer_0/angular_velocity = 0.0 -35:15/0 = 0 -35:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:15/0/physics_layer_0/angular_velocity = 0.0 -36:15/0 = 0 -36:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:15/0/physics_layer_0/angular_velocity = 0.0 -37:15/0 = 0 -37:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:15/0/physics_layer_0/angular_velocity = 0.0 -38:15/0 = 0 -38:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:15/0/physics_layer_0/angular_velocity = 0.0 -39:15/0 = 0 -39:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:15/0/physics_layer_0/angular_velocity = 0.0 -40:15/0 = 0 -40:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:15/0/physics_layer_0/angular_velocity = 0.0 -41:15/0 = 0 -41:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:15/0/physics_layer_0/angular_velocity = 0.0 -42:15/0 = 0 -42:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:15/0/physics_layer_0/angular_velocity = 0.0 -43:15/0 = 0 -43:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:15/0/physics_layer_0/angular_velocity = 0.0 -44:15/0 = 0 -44:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:15/0/physics_layer_0/angular_velocity = 0.0 -45:15/0 = 0 -45:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:15/0/physics_layer_0/angular_velocity = 0.0 -46:15/0 = 0 -46:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:15/0/physics_layer_0/angular_velocity = 0.0 -47:15/0 = 0 -47:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:15/0/physics_layer_0/angular_velocity = 0.0 -48:15/0 = 0 -48:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:15/0/physics_layer_0/angular_velocity = 0.0 -0:16/0 = 0 -0:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:16/0/physics_layer_0/angular_velocity = 0.0 -1:16/0 = 0 -1:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:16/0/physics_layer_0/angular_velocity = 0.0 -2:16/0 = 0 -2:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:16/0/physics_layer_0/angular_velocity = 0.0 -3:16/0 = 0 -3:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:16/0/physics_layer_0/angular_velocity = 0.0 -4:16/0 = 0 -4:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:16/0/physics_layer_0/angular_velocity = 0.0 -5:16/0 = 0 -5:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:16/0/physics_layer_0/angular_velocity = 0.0 -6:16/0 = 0 -6:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:16/0/physics_layer_0/angular_velocity = 0.0 -7:16/0 = 0 -7:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:16/0/physics_layer_0/angular_velocity = 0.0 -8:16/0 = 0 -8:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:16/0/physics_layer_0/angular_velocity = 0.0 -9:16/0 = 0 -9:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:16/0/physics_layer_0/angular_velocity = 0.0 -10:16/0 = 0 -10:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:16/0/physics_layer_0/angular_velocity = 0.0 -11:16/0 = 0 -11:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:16/0/physics_layer_0/angular_velocity = 0.0 -12:16/0 = 0 -12:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:16/0/physics_layer_0/angular_velocity = 0.0 -13:16/0 = 0 -13:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:16/0/physics_layer_0/angular_velocity = 0.0 -14:16/0 = 0 -14:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:16/0/physics_layer_0/angular_velocity = 0.0 -15:16/0 = 0 -15:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:16/0/physics_layer_0/angular_velocity = 0.0 -16:16/0 = 0 -16:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:16/0/physics_layer_0/angular_velocity = 0.0 -17:16/0 = 0 -17:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:16/0/physics_layer_0/angular_velocity = 0.0 -18:16/0 = 0 -18:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:16/0/physics_layer_0/angular_velocity = 0.0 -19:16/0 = 0 -19:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:16/0/physics_layer_0/angular_velocity = 0.0 -20:16/0 = 0 -20:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:16/0/physics_layer_0/angular_velocity = 0.0 -21:16/0 = 0 -21:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:16/0/physics_layer_0/angular_velocity = 0.0 -22:16/0 = 0 -22:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:16/0/physics_layer_0/angular_velocity = 0.0 -23:16/0 = 0 -23:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:16/0/physics_layer_0/angular_velocity = 0.0 -24:16/0 = 0 -24:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:16/0/physics_layer_0/angular_velocity = 0.0 -25:16/0 = 0 -25:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:16/0/physics_layer_0/angular_velocity = 0.0 -26:16/0 = 0 -26:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:16/0/physics_layer_0/angular_velocity = 0.0 -27:16/0 = 0 -27:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:16/0/physics_layer_0/angular_velocity = 0.0 -28:16/0 = 0 -28:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:16/0/physics_layer_0/angular_velocity = 0.0 -29:16/0 = 0 -29:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:16/0/physics_layer_0/angular_velocity = 0.0 -30:16/0 = 0 -30:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:16/0/physics_layer_0/angular_velocity = 0.0 -31:16/0 = 0 -31:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:16/0/physics_layer_0/angular_velocity = 0.0 -32:16/0 = 0 -32:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:16/0/physics_layer_0/angular_velocity = 0.0 -33:16/0 = 0 -33:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:16/0/physics_layer_0/angular_velocity = 0.0 -34:16/0 = 0 -34:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:16/0/physics_layer_0/angular_velocity = 0.0 -35:16/0 = 0 -35:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:16/0/physics_layer_0/angular_velocity = 0.0 -36:16/0 = 0 -36:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:16/0/physics_layer_0/angular_velocity = 0.0 -37:16/0 = 0 -37:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:16/0/physics_layer_0/angular_velocity = 0.0 -38:16/0 = 0 -38:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:16/0/physics_layer_0/angular_velocity = 0.0 -39:16/0 = 0 -39:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:16/0/physics_layer_0/angular_velocity = 0.0 -40:16/0 = 0 -40:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:16/0/physics_layer_0/angular_velocity = 0.0 -41:16/0 = 0 -41:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:16/0/physics_layer_0/angular_velocity = 0.0 -42:16/0 = 0 -42:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:16/0/physics_layer_0/angular_velocity = 0.0 -43:16/0 = 0 -43:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:16/0/physics_layer_0/angular_velocity = 0.0 -44:16/0 = 0 -44:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:16/0/physics_layer_0/angular_velocity = 0.0 -45:16/0 = 0 -45:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:16/0/physics_layer_0/angular_velocity = 0.0 -46:16/0 = 0 -46:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:16/0/physics_layer_0/angular_velocity = 0.0 -47:16/0 = 0 -47:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:16/0/physics_layer_0/angular_velocity = 0.0 -48:16/0 = 0 -48:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:16/0/physics_layer_0/angular_velocity = 0.0 -0:17/0 = 0 -0:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:17/0/physics_layer_0/angular_velocity = 0.0 -1:17/0 = 0 -1:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:17/0/physics_layer_0/angular_velocity = 0.0 -2:17/0 = 0 -2:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:17/0/physics_layer_0/angular_velocity = 0.0 -3:17/0 = 0 -3:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:17/0/physics_layer_0/angular_velocity = 0.0 -4:17/0 = 0 -4:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:17/0/physics_layer_0/angular_velocity = 0.0 -5:17/0 = 0 -5:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:17/0/physics_layer_0/angular_velocity = 0.0 -6:17/0 = 0 -6:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:17/0/physics_layer_0/angular_velocity = 0.0 -7:17/0 = 0 -7:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:17/0/physics_layer_0/angular_velocity = 0.0 -8:17/0 = 0 -8:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:17/0/physics_layer_0/angular_velocity = 0.0 -9:17/0 = 0 -9:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:17/0/physics_layer_0/angular_velocity = 0.0 -10:17/0 = 0 -10:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:17/0/physics_layer_0/angular_velocity = 0.0 -11:17/0 = 0 -11:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:17/0/physics_layer_0/angular_velocity = 0.0 -12:17/0 = 0 -12:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:17/0/physics_layer_0/angular_velocity = 0.0 -13:17/0 = 0 -13:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:17/0/physics_layer_0/angular_velocity = 0.0 -14:17/0 = 0 -14:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:17/0/physics_layer_0/angular_velocity = 0.0 -15:17/0 = 0 -15:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:17/0/physics_layer_0/angular_velocity = 0.0 -16:17/0 = 0 -16:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:17/0/physics_layer_0/angular_velocity = 0.0 -17:17/0 = 0 -17:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:17/0/physics_layer_0/angular_velocity = 0.0 -18:17/0 = 0 -18:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:17/0/physics_layer_0/angular_velocity = 0.0 -19:17/0 = 0 -19:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:17/0/physics_layer_0/angular_velocity = 0.0 -20:17/0 = 0 -20:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:17/0/physics_layer_0/angular_velocity = 0.0 -21:17/0 = 0 -21:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:17/0/physics_layer_0/angular_velocity = 0.0 -22:17/0 = 0 -22:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:17/0/physics_layer_0/angular_velocity = 0.0 -23:17/0 = 0 -23:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:17/0/physics_layer_0/angular_velocity = 0.0 -24:17/0 = 0 -24:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:17/0/physics_layer_0/angular_velocity = 0.0 -25:17/0 = 0 -25:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:17/0/physics_layer_0/angular_velocity = 0.0 -26:17/0 = 0 -26:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:17/0/physics_layer_0/angular_velocity = 0.0 -27:17/0 = 0 -27:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:17/0/physics_layer_0/angular_velocity = 0.0 -28:17/0 = 0 -28:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:17/0/physics_layer_0/angular_velocity = 0.0 -29:17/0 = 0 -29:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:17/0/physics_layer_0/angular_velocity = 0.0 -30:17/0 = 0 -30:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:17/0/physics_layer_0/angular_velocity = 0.0 -31:17/0 = 0 -31:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:17/0/physics_layer_0/angular_velocity = 0.0 -32:17/0 = 0 -32:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:17/0/physics_layer_0/angular_velocity = 0.0 -33:17/0 = 0 -33:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:17/0/physics_layer_0/angular_velocity = 0.0 -34:17/0 = 0 -34:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:17/0/physics_layer_0/angular_velocity = 0.0 -35:17/0 = 0 -35:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:17/0/physics_layer_0/angular_velocity = 0.0 -36:17/0 = 0 -36:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:17/0/physics_layer_0/angular_velocity = 0.0 -37:17/0 = 0 -37:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:17/0/physics_layer_0/angular_velocity = 0.0 -38:17/0 = 0 -38:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:17/0/physics_layer_0/angular_velocity = 0.0 -39:17/0 = 0 -39:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:17/0/physics_layer_0/angular_velocity = 0.0 -40:17/0 = 0 -40:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:17/0/physics_layer_0/angular_velocity = 0.0 -41:17/0 = 0 -41:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:17/0/physics_layer_0/angular_velocity = 0.0 -42:17/0 = 0 -42:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:17/0/physics_layer_0/angular_velocity = 0.0 -43:17/0 = 0 -43:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:17/0/physics_layer_0/angular_velocity = 0.0 -44:17/0 = 0 -44:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:17/0/physics_layer_0/angular_velocity = 0.0 -45:17/0 = 0 -45:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:17/0/physics_layer_0/angular_velocity = 0.0 -46:17/0 = 0 -46:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:17/0/physics_layer_0/angular_velocity = 0.0 -47:17/0 = 0 -47:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:17/0/physics_layer_0/angular_velocity = 0.0 -48:17/0 = 0 -48:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:17/0/physics_layer_0/angular_velocity = 0.0 -0:18/0 = 0 -0:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:18/0/physics_layer_0/angular_velocity = 0.0 -1:18/0 = 0 -1:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:18/0/physics_layer_0/angular_velocity = 0.0 -2:18/0 = 0 -2:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:18/0/physics_layer_0/angular_velocity = 0.0 -3:18/0 = 0 -3:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:18/0/physics_layer_0/angular_velocity = 0.0 -4:18/0 = 0 -4:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:18/0/physics_layer_0/angular_velocity = 0.0 -5:18/0 = 0 -5:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:18/0/physics_layer_0/angular_velocity = 0.0 -6:18/0 = 0 -6:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:18/0/physics_layer_0/angular_velocity = 0.0 -7:18/0 = 0 -7:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:18/0/physics_layer_0/angular_velocity = 0.0 -8:18/0 = 0 -8:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:18/0/physics_layer_0/angular_velocity = 0.0 -9:18/0 = 0 -9:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:18/0/physics_layer_0/angular_velocity = 0.0 -10:18/0 = 0 -10:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:18/0/physics_layer_0/angular_velocity = 0.0 -11:18/0 = 0 -11:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:18/0/physics_layer_0/angular_velocity = 0.0 -12:18/0 = 0 -12:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:18/0/physics_layer_0/angular_velocity = 0.0 -13:18/0 = 0 -13:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:18/0/physics_layer_0/angular_velocity = 0.0 -14:18/0 = 0 -14:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:18/0/physics_layer_0/angular_velocity = 0.0 -15:18/0 = 0 -15:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:18/0/physics_layer_0/angular_velocity = 0.0 -16:18/0 = 0 -16:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:18/0/physics_layer_0/angular_velocity = 0.0 -17:18/0 = 0 -17:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:18/0/physics_layer_0/angular_velocity = 0.0 -18:18/0 = 0 -18:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:18/0/physics_layer_0/angular_velocity = 0.0 -19:18/0 = 0 -19:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:18/0/physics_layer_0/angular_velocity = 0.0 -20:18/0 = 0 -20:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:18/0/physics_layer_0/angular_velocity = 0.0 -21:18/0 = 0 -21:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:18/0/physics_layer_0/angular_velocity = 0.0 -22:18/0 = 0 -22:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:18/0/physics_layer_0/angular_velocity = 0.0 -23:18/0 = 0 -23:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:18/0/physics_layer_0/angular_velocity = 0.0 -24:18/0 = 0 -24:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:18/0/physics_layer_0/angular_velocity = 0.0 -25:18/0 = 0 -25:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:18/0/physics_layer_0/angular_velocity = 0.0 -26:18/0 = 0 -26:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:18/0/physics_layer_0/angular_velocity = 0.0 -27:18/0 = 0 -27:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:18/0/physics_layer_0/angular_velocity = 0.0 -28:18/0 = 0 -28:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:18/0/physics_layer_0/angular_velocity = 0.0 -29:18/0 = 0 -29:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:18/0/physics_layer_0/angular_velocity = 0.0 -30:18/0 = 0 -30:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:18/0/physics_layer_0/angular_velocity = 0.0 -31:18/0 = 0 -31:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:18/0/physics_layer_0/angular_velocity = 0.0 -32:18/0 = 0 -32:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:18/0/physics_layer_0/angular_velocity = 0.0 -33:18/0 = 0 -33:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:18/0/physics_layer_0/angular_velocity = 0.0 -34:18/0 = 0 -34:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:18/0/physics_layer_0/angular_velocity = 0.0 -35:18/0 = 0 -35:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:18/0/physics_layer_0/angular_velocity = 0.0 -36:18/0 = 0 -36:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:18/0/physics_layer_0/angular_velocity = 0.0 -37:18/0 = 0 -37:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:18/0/physics_layer_0/angular_velocity = 0.0 -38:18/0 = 0 -38:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:18/0/physics_layer_0/angular_velocity = 0.0 -39:18/0 = 0 -39:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:18/0/physics_layer_0/angular_velocity = 0.0 -40:18/0 = 0 -40:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:18/0/physics_layer_0/angular_velocity = 0.0 -41:18/0 = 0 -41:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:18/0/physics_layer_0/angular_velocity = 0.0 -42:18/0 = 0 -42:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:18/0/physics_layer_0/angular_velocity = 0.0 -43:18/0 = 0 -43:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:18/0/physics_layer_0/angular_velocity = 0.0 -44:18/0 = 0 -44:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:18/0/physics_layer_0/angular_velocity = 0.0 -45:18/0 = 0 -45:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:18/0/physics_layer_0/angular_velocity = 0.0 -46:18/0 = 0 -46:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:18/0/physics_layer_0/angular_velocity = 0.0 -47:18/0 = 0 -47:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:18/0/physics_layer_0/angular_velocity = 0.0 -48:18/0 = 0 -48:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:18/0/physics_layer_0/angular_velocity = 0.0 -0:19/0 = 0 -0:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:19/0/physics_layer_0/angular_velocity = 0.0 -1:19/0 = 0 -1:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:19/0/physics_layer_0/angular_velocity = 0.0 -2:19/0 = 0 -2:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:19/0/physics_layer_0/angular_velocity = 0.0 -3:19/0 = 0 -3:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:19/0/physics_layer_0/angular_velocity = 0.0 -4:19/0 = 0 -4:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:19/0/physics_layer_0/angular_velocity = 0.0 -5:19/0 = 0 -5:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:19/0/physics_layer_0/angular_velocity = 0.0 -6:19/0 = 0 -6:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:19/0/physics_layer_0/angular_velocity = 0.0 -7:19/0 = 0 -7:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:19/0/physics_layer_0/angular_velocity = 0.0 -8:19/0 = 0 -8:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:19/0/physics_layer_0/angular_velocity = 0.0 -9:19/0 = 0 -9:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:19/0/physics_layer_0/angular_velocity = 0.0 -10:19/0 = 0 -10:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:19/0/physics_layer_0/angular_velocity = 0.0 -11:19/0 = 0 -11:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:19/0/physics_layer_0/angular_velocity = 0.0 -12:19/0 = 0 -12:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:19/0/physics_layer_0/angular_velocity = 0.0 -13:19/0 = 0 -13:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:19/0/physics_layer_0/angular_velocity = 0.0 -14:19/0 = 0 -14:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:19/0/physics_layer_0/angular_velocity = 0.0 -15:19/0 = 0 -15:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:19/0/physics_layer_0/angular_velocity = 0.0 -16:19/0 = 0 -16:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:19/0/physics_layer_0/angular_velocity = 0.0 -17:19/0 = 0 -17:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:19/0/physics_layer_0/angular_velocity = 0.0 -18:19/0 = 0 -18:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:19/0/physics_layer_0/angular_velocity = 0.0 -19:19/0 = 0 -19:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:19/0/physics_layer_0/angular_velocity = 0.0 -20:19/0 = 0 -20:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:19/0/physics_layer_0/angular_velocity = 0.0 -21:19/0 = 0 -21:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:19/0/physics_layer_0/angular_velocity = 0.0 -22:19/0 = 0 -22:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:19/0/physics_layer_0/angular_velocity = 0.0 -23:19/0 = 0 -23:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:19/0/physics_layer_0/angular_velocity = 0.0 -24:19/0 = 0 -24:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:19/0/physics_layer_0/angular_velocity = 0.0 -25:19/0 = 0 -25:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:19/0/physics_layer_0/angular_velocity = 0.0 -26:19/0 = 0 -26:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:19/0/physics_layer_0/angular_velocity = 0.0 -27:19/0 = 0 -27:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:19/0/physics_layer_0/angular_velocity = 0.0 -28:19/0 = 0 -28:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:19/0/physics_layer_0/angular_velocity = 0.0 -29:19/0 = 0 -29:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:19/0/physics_layer_0/angular_velocity = 0.0 -30:19/0 = 0 -30:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:19/0/physics_layer_0/angular_velocity = 0.0 -31:19/0 = 0 -31:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:19/0/physics_layer_0/angular_velocity = 0.0 -32:19/0 = 0 -32:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:19/0/physics_layer_0/angular_velocity = 0.0 -33:19/0 = 0 -33:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:19/0/physics_layer_0/angular_velocity = 0.0 -34:19/0 = 0 -34:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:19/0/physics_layer_0/angular_velocity = 0.0 -35:19/0 = 0 -35:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:19/0/physics_layer_0/angular_velocity = 0.0 -36:19/0 = 0 -36:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:19/0/physics_layer_0/angular_velocity = 0.0 -37:19/0 = 0 -37:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:19/0/physics_layer_0/angular_velocity = 0.0 -38:19/0 = 0 -38:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:19/0/physics_layer_0/angular_velocity = 0.0 -39:19/0 = 0 -39:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:19/0/physics_layer_0/angular_velocity = 0.0 -40:19/0 = 0 -40:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:19/0/physics_layer_0/angular_velocity = 0.0 -41:19/0 = 0 -41:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:19/0/physics_layer_0/angular_velocity = 0.0 -42:19/0 = 0 -42:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:19/0/physics_layer_0/angular_velocity = 0.0 -43:19/0 = 0 -43:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:19/0/physics_layer_0/angular_velocity = 0.0 -44:19/0 = 0 -44:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:19/0/physics_layer_0/angular_velocity = 0.0 -45:19/0 = 0 -45:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:19/0/physics_layer_0/angular_velocity = 0.0 -46:19/0 = 0 -46:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:19/0/physics_layer_0/angular_velocity = 0.0 -47:19/0 = 0 -47:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:19/0/physics_layer_0/angular_velocity = 0.0 -48:19/0 = 0 -48:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:19/0/physics_layer_0/angular_velocity = 0.0 -0:20/0 = 0 -0:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:20/0/physics_layer_0/angular_velocity = 0.0 -1:20/0 = 0 -1:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:20/0/physics_layer_0/angular_velocity = 0.0 -2:20/0 = 0 -2:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:20/0/physics_layer_0/angular_velocity = 0.0 -3:20/0 = 0 -3:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:20/0/physics_layer_0/angular_velocity = 0.0 -4:20/0 = 0 -4:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:20/0/physics_layer_0/angular_velocity = 0.0 -5:20/0 = 0 -5:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:20/0/physics_layer_0/angular_velocity = 0.0 -6:20/0 = 0 -6:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:20/0/physics_layer_0/angular_velocity = 0.0 -7:20/0 = 0 -7:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:20/0/physics_layer_0/angular_velocity = 0.0 -8:20/0 = 0 -8:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:20/0/physics_layer_0/angular_velocity = 0.0 -9:20/0 = 0 -9:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:20/0/physics_layer_0/angular_velocity = 0.0 -10:20/0 = 0 -10:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:20/0/physics_layer_0/angular_velocity = 0.0 -11:20/0 = 0 -11:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:20/0/physics_layer_0/angular_velocity = 0.0 -12:20/0 = 0 -12:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:20/0/physics_layer_0/angular_velocity = 0.0 -13:20/0 = 0 -13:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:20/0/physics_layer_0/angular_velocity = 0.0 -14:20/0 = 0 -14:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:20/0/physics_layer_0/angular_velocity = 0.0 -15:20/0 = 0 -15:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:20/0/physics_layer_0/angular_velocity = 0.0 -16:20/0 = 0 -16:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:20/0/physics_layer_0/angular_velocity = 0.0 -17:20/0 = 0 -17:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:20/0/physics_layer_0/angular_velocity = 0.0 -18:20/0 = 0 -18:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:20/0/physics_layer_0/angular_velocity = 0.0 -19:20/0 = 0 -19:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:20/0/physics_layer_0/angular_velocity = 0.0 -20:20/0 = 0 -20:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:20/0/physics_layer_0/angular_velocity = 0.0 -21:20/0 = 0 -21:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:20/0/physics_layer_0/angular_velocity = 0.0 -22:20/0 = 0 -22:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:20/0/physics_layer_0/angular_velocity = 0.0 -23:20/0 = 0 -23:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:20/0/physics_layer_0/angular_velocity = 0.0 -24:20/0 = 0 -24:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:20/0/physics_layer_0/angular_velocity = 0.0 -25:20/0 = 0 -25:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:20/0/physics_layer_0/angular_velocity = 0.0 -26:20/0 = 0 -26:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:20/0/physics_layer_0/angular_velocity = 0.0 -27:20/0 = 0 -27:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:20/0/physics_layer_0/angular_velocity = 0.0 -28:20/0 = 0 -28:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:20/0/physics_layer_0/angular_velocity = 0.0 -29:20/0 = 0 -29:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:20/0/physics_layer_0/angular_velocity = 0.0 -30:20/0 = 0 -30:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:20/0/physics_layer_0/angular_velocity = 0.0 -31:20/0 = 0 -31:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:20/0/physics_layer_0/angular_velocity = 0.0 -32:20/0 = 0 -32:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:20/0/physics_layer_0/angular_velocity = 0.0 -33:20/0 = 0 -33:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:20/0/physics_layer_0/angular_velocity = 0.0 -34:20/0 = 0 -34:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:20/0/physics_layer_0/angular_velocity = 0.0 -35:20/0 = 0 -35:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:20/0/physics_layer_0/angular_velocity = 0.0 -36:20/0 = 0 -36:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:20/0/physics_layer_0/angular_velocity = 0.0 -37:20/0 = 0 -37:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:20/0/physics_layer_0/angular_velocity = 0.0 -38:20/0 = 0 -38:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:20/0/physics_layer_0/angular_velocity = 0.0 -39:20/0 = 0 -39:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:20/0/physics_layer_0/angular_velocity = 0.0 -40:20/0 = 0 -40:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:20/0/physics_layer_0/angular_velocity = 0.0 -41:20/0 = 0 -41:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:20/0/physics_layer_0/angular_velocity = 0.0 -42:20/0 = 0 -42:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:20/0/physics_layer_0/angular_velocity = 0.0 -43:20/0 = 0 -43:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:20/0/physics_layer_0/angular_velocity = 0.0 -44:20/0 = 0 -44:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:20/0/physics_layer_0/angular_velocity = 0.0 -45:20/0 = 0 -45:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:20/0/physics_layer_0/angular_velocity = 0.0 -46:20/0 = 0 -46:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:20/0/physics_layer_0/angular_velocity = 0.0 -47:20/0 = 0 -47:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:20/0/physics_layer_0/angular_velocity = 0.0 -48:20/0 = 0 -48:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:20/0/physics_layer_0/angular_velocity = 0.0 -0:21/0 = 0 -0:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:21/0/physics_layer_0/angular_velocity = 0.0 -1:21/0 = 0 -1:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:21/0/physics_layer_0/angular_velocity = 0.0 -2:21/0 = 0 -2:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:21/0/physics_layer_0/angular_velocity = 0.0 -3:21/0 = 0 -3:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:21/0/physics_layer_0/angular_velocity = 0.0 -4:21/0 = 0 -4:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:21/0/physics_layer_0/angular_velocity = 0.0 -5:21/0 = 0 -5:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:21/0/physics_layer_0/angular_velocity = 0.0 -6:21/0 = 0 -6:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:21/0/physics_layer_0/angular_velocity = 0.0 -7:21/0 = 0 -7:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:21/0/physics_layer_0/angular_velocity = 0.0 -8:21/0 = 0 -8:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:21/0/physics_layer_0/angular_velocity = 0.0 -9:21/0 = 0 -9:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:21/0/physics_layer_0/angular_velocity = 0.0 -10:21/0 = 0 -10:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:21/0/physics_layer_0/angular_velocity = 0.0 -11:21/0 = 0 -11:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:21/0/physics_layer_0/angular_velocity = 0.0 -12:21/0 = 0 -12:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:21/0/physics_layer_0/angular_velocity = 0.0 -13:21/0 = 0 -13:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:21/0/physics_layer_0/angular_velocity = 0.0 -14:21/0 = 0 -14:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:21/0/physics_layer_0/angular_velocity = 0.0 -15:21/0 = 0 -15:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:21/0/physics_layer_0/angular_velocity = 0.0 -16:21/0 = 0 -16:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:21/0/physics_layer_0/angular_velocity = 0.0 -17:21/0 = 0 -17:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:21/0/physics_layer_0/angular_velocity = 0.0 -18:21/0 = 0 -18:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:21/0/physics_layer_0/angular_velocity = 0.0 -19:21/0 = 0 -19:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:21/0/physics_layer_0/angular_velocity = 0.0 -20:21/0 = 0 -20:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:21/0/physics_layer_0/angular_velocity = 0.0 -21:21/0 = 0 -21:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:21/0/physics_layer_0/angular_velocity = 0.0 -22:21/0 = 0 -22:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:21/0/physics_layer_0/angular_velocity = 0.0 -23:21/0 = 0 -23:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:21/0/physics_layer_0/angular_velocity = 0.0 -24:21/0 = 0 -24:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:21/0/physics_layer_0/angular_velocity = 0.0 -25:21/0 = 0 -25:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:21/0/physics_layer_0/angular_velocity = 0.0 -26:21/0 = 0 -26:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:21/0/physics_layer_0/angular_velocity = 0.0 -27:21/0 = 0 -27:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:21/0/physics_layer_0/angular_velocity = 0.0 -28:21/0 = 0 -28:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:21/0/physics_layer_0/angular_velocity = 0.0 -29:21/0 = 0 -29:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:21/0/physics_layer_0/angular_velocity = 0.0 -30:21/0 = 0 -30:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:21/0/physics_layer_0/angular_velocity = 0.0 -31:21/0 = 0 -31:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:21/0/physics_layer_0/angular_velocity = 0.0 -32:21/0 = 0 -32:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:21/0/physics_layer_0/angular_velocity = 0.0 -33:21/0 = 0 -33:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:21/0/physics_layer_0/angular_velocity = 0.0 -34:21/0 = 0 -34:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:21/0/physics_layer_0/angular_velocity = 0.0 -35:21/0 = 0 -35:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:21/0/physics_layer_0/angular_velocity = 0.0 -36:21/0 = 0 -36:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:21/0/physics_layer_0/angular_velocity = 0.0 -37:21/0 = 0 -37:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:21/0/physics_layer_0/angular_velocity = 0.0 -38:21/0 = 0 -38:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:21/0/physics_layer_0/angular_velocity = 0.0 -39:21/0 = 0 -39:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:21/0/physics_layer_0/angular_velocity = 0.0 -40:21/0 = 0 -40:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:21/0/physics_layer_0/angular_velocity = 0.0 -41:21/0 = 0 -41:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:21/0/physics_layer_0/angular_velocity = 0.0 -42:21/0 = 0 -42:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:21/0/physics_layer_0/angular_velocity = 0.0 -43:21/0 = 0 -43:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:21/0/physics_layer_0/angular_velocity = 0.0 -44:21/0 = 0 -44:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:21/0/physics_layer_0/angular_velocity = 0.0 -45:21/0 = 0 -45:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:21/0/physics_layer_0/angular_velocity = 0.0 -46:21/0 = 0 -46:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:21/0/physics_layer_0/angular_velocity = 0.0 -47:21/0 = 0 -47:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:21/0/physics_layer_0/angular_velocity = 0.0 -48:21/0 = 0 -48:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:21/0/physics_layer_0/angular_velocity = 0.0 -18:0/0 = 0 -18:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:0/0/physics_layer_0/angular_velocity = 0.0 -18:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) - -[sub_resource type="TileSetScenesCollectionSource" id="TileSetScenesCollectionSource_mi6dp"] -scenes/1/scene = ExtResource("2_win2x") - -[sub_resource type="TileSet" id="TileSet_0u0tf"] -physics_layer_0/collision_layer = 1 -sources/1 = SubResource("TileSetAtlasSource_ari5a") -sources/3 = SubResource("TileSetScenesCollectionSource_mi6dp") +[ext_resource type="Texture2D" uid="uid://5kstmna3yb6t" path="res://assets/white.png" id="6_8laen"] +[ext_resource type="FontFile" uid="uid://ddjw625xpmwtc" path="res://assets/Not Jam UI Condensed 16.ttf" id="6_sa7lc"] [node name="Main" type="Node2D"] script = ExtResource("1_8hq0w") @@ -3262,16 +14,10 @@ script = ExtResource("1_8hq0w") [node name="Player" parent="." instance=ExtResource("2_ekt33")] position = Vector2(80, 48) -[node name="Map" type="Node2D" parent="."] - -[node name="TileMap" type="TileMap" parent="Map"] -tile_set = SubResource("TileSet_0u0tf") -format = 2 -layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 196617, 0, 131072) -layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 262152, 3, 65536, 327689, 3, 65536, 327690, 3, 65536, 327691, 3, 65536, 262156, 3, 65536, 196620, 3, 65536, 131084, 3, 65536, 131083, 3, 65536, 131082, 3, 65536, 131081, 3, 65536, 196617, 3, 65536, 196616, 3, 65536, 327688, 3, 65536, 393224, 3, 65536, 393225, 3, 65536, 458761, 3, 65536, 458762, 3, 65536, 458763, 3, 65536, 458764, 3, 65536, 393228, 3, 65536, 393229, 3, 65536, 327693, 3, 65536, 262157, 3, 65536, 196621, 3, 65536, 131085, 3, 65536, 65548, 3, 65536, 65547, 3, 65536, 65546, 3, 65536, 65545, 3, 65536, 65544, 3, 65536, 65549, 3, 65536, 131086, 3, 65536, 196622, 3, 65536, 196623, 3, 65536) +[node name="Map" parent="." instance=ExtResource("3_w444g")] [node name="UI" type="Control" parent="."] +top_level = true layout_mode = 3 anchors_preset = 0 offset_right = 256.0 @@ -3290,6 +36,57 @@ offset_bottom = 128.0 layout_mode = 0 offset_right = 224.0 offset_bottom = 32.0 -theme_override_font_sizes/font_size = 10 +theme_override_fonts/font = ExtResource("6_sa7lc") +theme_override_font_sizes/font_size = 16 text = "I told you to not let Jayden make the ui bruh!!!" autowrap_mode = 2 + +[node name="HUD" type="Control" parent="UI"] +anchors_preset = 0 +offset_right = 256.0 +offset_bottom = 16.0 + +[node name="Bar" type="TextureRect" parent="UI/HUD"] +layout_mode = 2 +offset_right = 256.0 +offset_bottom = 17.0 +texture = ExtResource("6_8laen") + +[node name="BootIcon" type="Sprite2D" parent="UI/HUD"] +visible = false +modulate = Color(0, 0, 0, 1) +position = Vector2(160, 0) +texture = ExtResource("1_kghfi") +centered = false +region_enabled = true +region_rect = Rect2(640, 16, 16, 16) + +[node name="HPLabel" type="Label" parent="UI/HUD"] +layout_mode = 2 +offset_left = 16.0 +offset_right = 54.0 +offset_bottom = 16.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_fonts/font = ExtResource("6_sa7lc") +theme_override_font_sizes/font_size = 16 +text = "HP: 3/3" + +[node name="HPLabel2" type="Label" parent="UI/HUD"] +layout_mode = 2 +offset_left = 192.0 +offset_right = 206.0 +offset_bottom = 16.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_fonts/font = ExtResource("6_sa7lc") +theme_override_font_sizes/font_size = 16 +text = "0g" + +[node name="HPLabel3" type="Label" parent="UI/HUD"] +layout_mode = 2 +offset_left = 224.0 +offset_right = 262.0 +offset_bottom = 16.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_fonts/font = ExtResource("6_sa7lc") +theme_override_font_sizes/font_size = 16 +text = "B00" diff --git a/src/main/ui.gd b/src/main/ui.gd index 9d0ea58..bdde533 100644 --- a/src/main/ui.gd +++ b/src/main/ui.gd @@ -2,6 +2,7 @@ class_name UI extends Control @onready var textbox:Panel = $Textbox +@onready var bootIcon:Sprite2D =$HUD/BootIcon signal text_rendered signal text_removed signal text_advanced @@ -10,6 +11,7 @@ signal text_advanced func render_text(new_text_arr) -> void: #loop through the array and display the lines of text text_rendered.emit() + bootIcon.visible = true textbox.visible = true var textLabel = $Textbox/Text #i = 0 diff --git a/src/maps/map-1.tscn b/src/maps/map-1.tscn new file mode 100644 index 0000000..5699bf0 --- /dev/null +++ b/src/maps/map-1.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=3 format=3 uid="uid://deqm4to4ptnq0"] + +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_vosps"] +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_web8r"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_web8r") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("1_vosps") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 196615, 3, 262144, 393226, 3, 196608) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 48) diff --git a/src/maps/map-2.tscn b/src/maps/map-2.tscn new file mode 100644 index 0000000..edb017b --- /dev/null +++ b/src/maps/map-2.tscn @@ -0,0 +1,15 @@ +[gd_scene load_steps=2 format=3 uid="uid://cwxdotd7hh5tb"] + +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_2mk3g"] + +[node name="Map" type="Node2D"] + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("1_2mk3g") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 393219, 3, 196608, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 64) diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn new file mode 100644 index 0000000..192567e --- /dev/null +++ b/src/maps/map-3.tscn @@ -0,0 +1,15 @@ +[gd_scene load_steps=2 format=3 uid="uid://bapnj7ekqfb0t"] + +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_xfyi1"] + +[node name="Map" type="Node2D"] + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("1_xfyi1") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458762, 262145, 18, 458761, 262145, 18, 65550, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 262157, 262145, 18, 196621, 262145, 18, 196620, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 327688, 262145, 18, 393224, 262145, 18, 393223, 262145, 18, 327687, 262145, 18, 327686, 262145, 18, 262150, 262145, 18, 196614, 262145, 18, 196613, 262145, 18, 196612, 262145, 18, 262148, 262145, 18, 262147, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 327685, 262145, 18, 393225, 262145, 18, 393226, 262145, 18, 393227, 262145, 18, 393228, 262145, 18, 393229, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 327693, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 196615, 262145, 18, 262151, 262145, 18, 131082, 3, 262144, 327692, 3, 196608) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(144, 48) diff --git a/src/maps/map.gd b/src/maps/map.gd new file mode 100644 index 0000000..fe88449 --- /dev/null +++ b/src/maps/map.gd @@ -0,0 +1,12 @@ +class_name Map +extends Node2D + + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + pass diff --git a/src/player/player.gd b/src/player/player.gd index db267f8..a6bfd75 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -3,6 +3,8 @@ extends Area2D @onready var raycast := $RayCast2D +signal walked_into_stairs + const TILE_SIZE := 16 var is_actionable:= true @@ -12,6 +14,7 @@ func _init() -> void: func _ready() -> void: raycast.collide_with_areas = true + func get_input_vector(event: InputEvent) -> Vector2: # make vector representing player input var dir := Vector2.ZERO @@ -39,7 +42,6 @@ func _input(event: InputEvent) -> void: _inspect() - func _move(_input_dir:Vector2) -> void: raycast.target_position = _input_dir * TILE_SIZE # clear old raycast collison then get new one @@ -48,8 +50,11 @@ func _move(_input_dir:Vector2) -> void: if next_tile != null: print(next_tile) - else: + + if next_tile == null: position += _input_dir * TILE_SIZE + elif next_tile.is_in_group('stairs'): + walked_into_stairs.emit() func _inspect() -> void: diff --git a/src/player/player.tscn b/src/player/player.tscn index e362576..6c7d3be 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -9,16 +9,16 @@ size = Vector2(16, 16) [node name="Player" type="Area2D"] script = ExtResource("1_fqi5k") +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(8, 8) +shape = SubResource("RectangleShape2D_v5s8d") + [node name="Sprite2D" type="Sprite2D" parent="."] texture = ExtResource("1_bwexj") centered = false region_enabled = true region_rect = Rect2(432, 0, 16, 16) -[node name="CollisionShape2D" type="CollisionShape2D" parent="."] -position = Vector2(8, 8) -shape = SubResource("RectangleShape2D_v5s8d") - [node name="RayCast2D" type="RayCast2D" parent="."] position = Vector2(8, 8) target_position = Vector2(0, 16) diff --git a/src/resources/map_tileset.tres b/src/resources/map_tileset.tres new file mode 100644 index 0000000..e471ef7 --- /dev/null +++ b/src/resources/map_tileset.tres @@ -0,0 +1,3256 @@ +[gd_resource type="TileSet" load_steps=6 format=3 uid="uid://dmwbt07hsdtyl"] + +[ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_q6o4g"] +[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="2_poklm"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_uqirg"] + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ari5a"] +texture = ExtResource("1_q6o4g") +1:0/0 = 0 +1:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:0/0/physics_layer_0/angular_velocity = 0.0 +2:0/0 = 0 +2:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:0/0/physics_layer_0/angular_velocity = 0.0 +3:0/0 = 0 +3:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:0/0/physics_layer_0/angular_velocity = 0.0 +4:0/0 = 0 +4:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:0/0/physics_layer_0/angular_velocity = 0.0 +5:0/0 = 0 +5:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:0/0/physics_layer_0/angular_velocity = 0.0 +6:0/0 = 0 +6:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:0/0/physics_layer_0/angular_velocity = 0.0 +7:0/0 = 0 +7:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:0/0/physics_layer_0/angular_velocity = 0.0 +8:0/0 = 0 +8:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:0/0/physics_layer_0/angular_velocity = 0.0 +9:0/0 = 0 +9:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:0/0/physics_layer_0/angular_velocity = 0.0 +10:0/0 = 0 +10:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:0/0/physics_layer_0/angular_velocity = 0.0 +11:0/0 = 0 +11:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:0/0/physics_layer_0/angular_velocity = 0.0 +12:0/0 = 0 +12:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:0/0/physics_layer_0/angular_velocity = 0.0 +13:0/0 = 0 +13:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:0/0/physics_layer_0/angular_velocity = 0.0 +14:0/0 = 0 +14:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:0/0/physics_layer_0/angular_velocity = 0.0 +15:0/0 = 0 +15:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:0/0/physics_layer_0/angular_velocity = 0.0 +16:0/0 = 0 +16:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:0/0/physics_layer_0/angular_velocity = 0.0 +17:0/0 = 0 +17:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:0/0/physics_layer_0/angular_velocity = 0.0 +19:0/0 = 0 +19:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:0/0/physics_layer_0/angular_velocity = 0.0 +19:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +20:0/0 = 0 +20:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:0/0/physics_layer_0/angular_velocity = 0.0 +20:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +21:0/0 = 0 +21:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:0/0/physics_layer_0/angular_velocity = 0.0 +22:0/0 = 0 +22:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:0/0/physics_layer_0/angular_velocity = 0.0 +23:0/0 = 0 +23:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:0/0/physics_layer_0/angular_velocity = 0.0 +24:0/0 = 0 +24:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:0/0/physics_layer_0/angular_velocity = 0.0 +25:0/0 = 0 +25:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:0/0/physics_layer_0/angular_velocity = 0.0 +26:0/0 = 0 +26:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:0/0/physics_layer_0/angular_velocity = 0.0 +27:0/0 = 0 +27:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:0/0/physics_layer_0/angular_velocity = 0.0 +28:0/0 = 0 +28:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:0/0/physics_layer_0/angular_velocity = 0.0 +29:0/0 = 0 +29:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:0/0/physics_layer_0/angular_velocity = 0.0 +30:0/0 = 0 +30:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:0/0/physics_layer_0/angular_velocity = 0.0 +31:0/0 = 0 +31:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:0/0/physics_layer_0/angular_velocity = 0.0 +32:0/0 = 0 +32:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:0/0/physics_layer_0/angular_velocity = 0.0 +33:0/0 = 0 +33:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:0/0/physics_layer_0/angular_velocity = 0.0 +34:0/0 = 0 +34:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:0/0/physics_layer_0/angular_velocity = 0.0 +35:0/0 = 0 +35:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:0/0/physics_layer_0/angular_velocity = 0.0 +36:0/0 = 0 +36:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:0/0/physics_layer_0/angular_velocity = 0.0 +37:0/0 = 0 +37:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:0/0/physics_layer_0/angular_velocity = 0.0 +38:0/0 = 0 +38:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:0/0/physics_layer_0/angular_velocity = 0.0 +39:0/0 = 0 +39:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:0/0/physics_layer_0/angular_velocity = 0.0 +40:0/0 = 0 +40:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:0/0/physics_layer_0/angular_velocity = 0.0 +41:0/0 = 0 +41:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:0/0/physics_layer_0/angular_velocity = 0.0 +42:0/0 = 0 +42:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:0/0/physics_layer_0/angular_velocity = 0.0 +43:0/0 = 0 +43:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:0/0/physics_layer_0/angular_velocity = 0.0 +44:0/0 = 0 +44:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:0/0/physics_layer_0/angular_velocity = 0.0 +45:0/0 = 0 +45:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:0/0/physics_layer_0/angular_velocity = 0.0 +46:0/0 = 0 +46:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:0/0/physics_layer_0/angular_velocity = 0.0 +47:0/0 = 0 +47:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:0/0/physics_layer_0/angular_velocity = 0.0 +48:0/0 = 0 +48:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:0/0/physics_layer_0/angular_velocity = 0.0 +0:1/0 = 0 +0:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:1/0/physics_layer_0/angular_velocity = 0.0 +1:1/0 = 0 +1:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:1/0/physics_layer_0/angular_velocity = 0.0 +2:1/0 = 0 +2:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:1/0/physics_layer_0/angular_velocity = 0.0 +3:1/0 = 0 +3:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:1/0/physics_layer_0/angular_velocity = 0.0 +4:1/0 = 0 +4:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:1/0/physics_layer_0/angular_velocity = 0.0 +5:1/0 = 0 +5:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:1/0/physics_layer_0/angular_velocity = 0.0 +6:1/0 = 0 +6:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:1/0/physics_layer_0/angular_velocity = 0.0 +7:1/0 = 0 +7:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:1/0/physics_layer_0/angular_velocity = 0.0 +8:1/0 = 0 +8:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:1/0/physics_layer_0/angular_velocity = 0.0 +9:1/0 = 0 +9:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:1/0/physics_layer_0/angular_velocity = 0.0 +10:1/0 = 0 +10:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:1/0/physics_layer_0/angular_velocity = 0.0 +11:1/0 = 0 +11:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:1/0/physics_layer_0/angular_velocity = 0.0 +12:1/0 = 0 +12:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:1/0/physics_layer_0/angular_velocity = 0.0 +13:1/0 = 0 +13:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:1/0/physics_layer_0/angular_velocity = 0.0 +14:1/0 = 0 +14:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:1/0/physics_layer_0/angular_velocity = 0.0 +15:1/0 = 0 +15:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:1/0/physics_layer_0/angular_velocity = 0.0 +16:1/0 = 0 +16:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:1/0/physics_layer_0/angular_velocity = 0.0 +17:1/0 = 0 +17:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:1/0/physics_layer_0/angular_velocity = 0.0 +18:1/0 = 0 +18:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:1/0/physics_layer_0/angular_velocity = 0.0 +18:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +19:1/0 = 0 +19:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:1/0/physics_layer_0/angular_velocity = 0.0 +20:1/0 = 0 +20:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:1/0/physics_layer_0/angular_velocity = 0.0 +20:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +21:1/0 = 0 +21:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:1/0/physics_layer_0/angular_velocity = 0.0 +22:1/0 = 0 +22:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:1/0/physics_layer_0/angular_velocity = 0.0 +23:1/0 = 0 +23:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:1/0/physics_layer_0/angular_velocity = 0.0 +24:1/0 = 0 +24:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:1/0/physics_layer_0/angular_velocity = 0.0 +25:1/0 = 0 +25:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:1/0/physics_layer_0/angular_velocity = 0.0 +26:1/0 = 0 +26:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:1/0/physics_layer_0/angular_velocity = 0.0 +27:1/0 = 0 +27:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:1/0/physics_layer_0/angular_velocity = 0.0 +28:1/0 = 0 +28:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:1/0/physics_layer_0/angular_velocity = 0.0 +29:1/0 = 0 +29:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:1/0/physics_layer_0/angular_velocity = 0.0 +30:1/0 = 0 +30:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:1/0/physics_layer_0/angular_velocity = 0.0 +31:1/0 = 0 +31:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:1/0/physics_layer_0/angular_velocity = 0.0 +32:1/0 = 0 +32:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:1/0/physics_layer_0/angular_velocity = 0.0 +33:1/0 = 0 +33:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:1/0/physics_layer_0/angular_velocity = 0.0 +34:1/0 = 0 +34:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:1/0/physics_layer_0/angular_velocity = 0.0 +35:1/0 = 0 +35:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:1/0/physics_layer_0/angular_velocity = 0.0 +36:1/0 = 0 +36:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:1/0/physics_layer_0/angular_velocity = 0.0 +37:1/0 = 0 +37:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:1/0/physics_layer_0/angular_velocity = 0.0 +38:1/0 = 0 +38:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:1/0/physics_layer_0/angular_velocity = 0.0 +39:1/0 = 0 +39:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:1/0/physics_layer_0/angular_velocity = 0.0 +40:1/0 = 0 +40:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:1/0/physics_layer_0/angular_velocity = 0.0 +41:1/0 = 0 +41:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:1/0/physics_layer_0/angular_velocity = 0.0 +42:1/0 = 0 +42:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:1/0/physics_layer_0/angular_velocity = 0.0 +43:1/0 = 0 +43:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:1/0/physics_layer_0/angular_velocity = 0.0 +44:1/0 = 0 +44:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:1/0/physics_layer_0/angular_velocity = 0.0 +45:1/0 = 0 +45:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:1/0/physics_layer_0/angular_velocity = 0.0 +46:1/0 = 0 +46:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:1/0/physics_layer_0/angular_velocity = 0.0 +47:1/0 = 0 +47:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:1/0/physics_layer_0/angular_velocity = 0.0 +48:1/0 = 0 +48:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:1/0/physics_layer_0/angular_velocity = 0.0 +0:2/0 = 0 +0:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:2/0/physics_layer_0/angular_velocity = 0.0 +1:2/0 = 0 +1:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:2/0/physics_layer_0/angular_velocity = 0.0 +2:2/0 = 0 +2:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:2/0/physics_layer_0/angular_velocity = 0.0 +3:2/0 = 0 +3:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:2/0/physics_layer_0/angular_velocity = 0.0 +4:2/0 = 0 +4:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:2/0/physics_layer_0/angular_velocity = 0.0 +5:2/0 = 0 +5:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:2/0/physics_layer_0/angular_velocity = 0.0 +6:2/0 = 0 +6:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:2/0/physics_layer_0/angular_velocity = 0.0 +7:2/0 = 0 +7:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:2/0/physics_layer_0/angular_velocity = 0.0 +8:2/0 = 0 +8:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:2/0/physics_layer_0/angular_velocity = 0.0 +9:2/0 = 0 +9:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:2/0/physics_layer_0/angular_velocity = 0.0 +10:2/0 = 0 +10:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:2/0/physics_layer_0/angular_velocity = 0.0 +11:2/0 = 0 +11:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:2/0/physics_layer_0/angular_velocity = 0.0 +12:2/0 = 0 +12:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:2/0/physics_layer_0/angular_velocity = 0.0 +13:2/0 = 0 +13:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:2/0/physics_layer_0/angular_velocity = 0.0 +14:2/0 = 0 +14:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:2/0/physics_layer_0/angular_velocity = 0.0 +15:2/0 = 0 +15:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:2/0/physics_layer_0/angular_velocity = 0.0 +16:2/0 = 0 +16:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:2/0/physics_layer_0/angular_velocity = 0.0 +17:2/0 = 0 +17:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:2/0/physics_layer_0/angular_velocity = 0.0 +18:2/0 = 0 +18:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:2/0/physics_layer_0/angular_velocity = 0.0 +18:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +19:2/0 = 0 +19:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:2/0/physics_layer_0/angular_velocity = 0.0 +19:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +20:2/0 = 0 +20:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:2/0/physics_layer_0/angular_velocity = 0.0 +20:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +21:2/0 = 0 +21:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:2/0/physics_layer_0/angular_velocity = 0.0 +22:2/0 = 0 +22:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:2/0/physics_layer_0/angular_velocity = 0.0 +23:2/0 = 0 +23:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:2/0/physics_layer_0/angular_velocity = 0.0 +24:2/0 = 0 +24:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:2/0/physics_layer_0/angular_velocity = 0.0 +25:2/0 = 0 +25:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:2/0/physics_layer_0/angular_velocity = 0.0 +26:2/0 = 0 +26:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:2/0/physics_layer_0/angular_velocity = 0.0 +27:2/0 = 0 +27:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:2/0/physics_layer_0/angular_velocity = 0.0 +28:2/0 = 0 +28:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:2/0/physics_layer_0/angular_velocity = 0.0 +29:2/0 = 0 +29:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:2/0/physics_layer_0/angular_velocity = 0.0 +30:2/0 = 0 +30:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:2/0/physics_layer_0/angular_velocity = 0.0 +31:2/0 = 0 +31:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:2/0/physics_layer_0/angular_velocity = 0.0 +32:2/0 = 0 +32:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:2/0/physics_layer_0/angular_velocity = 0.0 +33:2/0 = 0 +33:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:2/0/physics_layer_0/angular_velocity = 0.0 +34:2/0 = 0 +34:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:2/0/physics_layer_0/angular_velocity = 0.0 +35:2/0 = 0 +35:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:2/0/physics_layer_0/angular_velocity = 0.0 +36:2/0 = 0 +36:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:2/0/physics_layer_0/angular_velocity = 0.0 +37:2/0 = 0 +37:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:2/0/physics_layer_0/angular_velocity = 0.0 +38:2/0 = 0 +38:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:2/0/physics_layer_0/angular_velocity = 0.0 +39:2/0 = 0 +39:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:2/0/physics_layer_0/angular_velocity = 0.0 +40:2/0 = 0 +40:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:2/0/physics_layer_0/angular_velocity = 0.0 +41:2/0 = 0 +41:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:2/0/physics_layer_0/angular_velocity = 0.0 +42:2/0 = 0 +42:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:2/0/physics_layer_0/angular_velocity = 0.0 +43:2/0 = 0 +43:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:2/0/physics_layer_0/angular_velocity = 0.0 +44:2/0 = 0 +44:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:2/0/physics_layer_0/angular_velocity = 0.0 +45:2/0 = 0 +45:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:2/0/physics_layer_0/angular_velocity = 0.0 +46:2/0 = 0 +46:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:2/0/physics_layer_0/angular_velocity = 0.0 +47:2/0 = 0 +47:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:2/0/physics_layer_0/angular_velocity = 0.0 +48:2/0 = 0 +48:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:2/0/physics_layer_0/angular_velocity = 0.0 +0:3/0 = 0 +0:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:3/0/physics_layer_0/angular_velocity = 0.0 +1:3/0 = 0 +1:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:3/0/physics_layer_0/angular_velocity = 0.0 +2:3/0 = 0 +2:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:3/0/physics_layer_0/angular_velocity = 0.0 +3:3/0 = 0 +3:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:3/0/physics_layer_0/angular_velocity = 0.0 +4:3/0 = 0 +4:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:3/0/physics_layer_0/angular_velocity = 0.0 +5:3/0 = 0 +5:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:3/0/physics_layer_0/angular_velocity = 0.0 +6:3/0 = 0 +6:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:3/0/physics_layer_0/angular_velocity = 0.0 +7:3/0 = 0 +7:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:3/0/physics_layer_0/angular_velocity = 0.0 +8:3/0 = 0 +8:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:3/0/physics_layer_0/angular_velocity = 0.0 +9:3/0 = 0 +9:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:3/0/physics_layer_0/angular_velocity = 0.0 +10:3/0 = 0 +10:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:3/0/physics_layer_0/angular_velocity = 0.0 +11:3/0 = 0 +11:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:3/0/physics_layer_0/angular_velocity = 0.0 +12:3/0 = 0 +12:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:3/0/physics_layer_0/angular_velocity = 0.0 +13:3/0 = 0 +13:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:3/0/physics_layer_0/angular_velocity = 0.0 +14:3/0 = 0 +14:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:3/0/physics_layer_0/angular_velocity = 0.0 +15:3/0 = 0 +15:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:3/0/physics_layer_0/angular_velocity = 0.0 +16:3/0 = 0 +16:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:3/0/physics_layer_0/angular_velocity = 0.0 +17:3/0 = 0 +17:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:3/0/physics_layer_0/angular_velocity = 0.0 +18:3/0 = 0 +18:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:3/0/physics_layer_0/angular_velocity = 0.0 +19:3/0 = 0 +19:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:3/0/physics_layer_0/angular_velocity = 0.0 +20:3/0 = 0 +20:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:3/0/physics_layer_0/angular_velocity = 0.0 +21:3/0 = 0 +21:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:3/0/physics_layer_0/angular_velocity = 0.0 +22:3/0 = 0 +22:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:3/0/physics_layer_0/angular_velocity = 0.0 +23:3/0 = 0 +23:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:3/0/physics_layer_0/angular_velocity = 0.0 +24:3/0 = 0 +24:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:3/0/physics_layer_0/angular_velocity = 0.0 +25:3/0 = 0 +25:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:3/0/physics_layer_0/angular_velocity = 0.0 +26:3/0 = 0 +26:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:3/0/physics_layer_0/angular_velocity = 0.0 +27:3/0 = 0 +27:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:3/0/physics_layer_0/angular_velocity = 0.0 +28:3/0 = 0 +28:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:3/0/physics_layer_0/angular_velocity = 0.0 +29:3/0 = 0 +29:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:3/0/physics_layer_0/angular_velocity = 0.0 +30:3/0 = 0 +30:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:3/0/physics_layer_0/angular_velocity = 0.0 +31:3/0 = 0 +31:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:3/0/physics_layer_0/angular_velocity = 0.0 +32:3/0 = 0 +32:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:3/0/physics_layer_0/angular_velocity = 0.0 +33:3/0 = 0 +33:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:3/0/physics_layer_0/angular_velocity = 0.0 +34:3/0 = 0 +34:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:3/0/physics_layer_0/angular_velocity = 0.0 +35:3/0 = 0 +35:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:3/0/physics_layer_0/angular_velocity = 0.0 +36:3/0 = 0 +36:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:3/0/physics_layer_0/angular_velocity = 0.0 +37:3/0 = 0 +37:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:3/0/physics_layer_0/angular_velocity = 0.0 +38:3/0 = 0 +38:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:3/0/physics_layer_0/angular_velocity = 0.0 +39:3/0 = 0 +39:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:3/0/physics_layer_0/angular_velocity = 0.0 +40:3/0 = 0 +40:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:3/0/physics_layer_0/angular_velocity = 0.0 +41:3/0 = 0 +41:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:3/0/physics_layer_0/angular_velocity = 0.0 +42:3/0 = 0 +42:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:3/0/physics_layer_0/angular_velocity = 0.0 +43:3/0 = 0 +43:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:3/0/physics_layer_0/angular_velocity = 0.0 +44:3/0 = 0 +44:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:3/0/physics_layer_0/angular_velocity = 0.0 +45:3/0 = 0 +45:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:3/0/physics_layer_0/angular_velocity = 0.0 +46:3/0 = 0 +46:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:3/0/physics_layer_0/angular_velocity = 0.0 +47:3/0 = 0 +47:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:3/0/physics_layer_0/angular_velocity = 0.0 +48:3/0 = 0 +48:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:3/0/physics_layer_0/angular_velocity = 0.0 +0:4/0 = 0 +0:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:4/0/physics_layer_0/angular_velocity = 0.0 +1:4/0 = 0 +1:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:4/0/physics_layer_0/angular_velocity = 0.0 +2:4/0 = 0 +2:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:4/0/physics_layer_0/angular_velocity = 0.0 +3:4/0 = 0 +3:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:4/0/physics_layer_0/angular_velocity = 0.0 +4:4/0 = 0 +4:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:4/0/physics_layer_0/angular_velocity = 0.0 +5:4/0 = 0 +5:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:4/0/physics_layer_0/angular_velocity = 0.0 +6:4/0 = 0 +6:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:4/0/physics_layer_0/angular_velocity = 0.0 +7:4/0 = 0 +7:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:4/0/physics_layer_0/angular_velocity = 0.0 +8:4/0 = 0 +8:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:4/0/physics_layer_0/angular_velocity = 0.0 +9:4/0 = 0 +9:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:4/0/physics_layer_0/angular_velocity = 0.0 +10:4/0 = 0 +10:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:4/0/physics_layer_0/angular_velocity = 0.0 +11:4/0 = 0 +11:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:4/0/physics_layer_0/angular_velocity = 0.0 +12:4/0 = 0 +12:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:4/0/physics_layer_0/angular_velocity = 0.0 +13:4/0 = 0 +13:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:4/0/physics_layer_0/angular_velocity = 0.0 +14:4/0 = 0 +14:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:4/0/physics_layer_0/angular_velocity = 0.0 +15:4/0 = 0 +15:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:4/0/physics_layer_0/angular_velocity = 0.0 +16:4/0 = 0 +16:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:4/0/physics_layer_0/angular_velocity = 0.0 +17:4/0 = 0 +17:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:4/0/physics_layer_0/angular_velocity = 0.0 +18:4/0 = 0 +18:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:4/0/physics_layer_0/angular_velocity = 0.0 +19:4/0 = 0 +19:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:4/0/physics_layer_0/angular_velocity = 0.0 +20:4/0 = 0 +20:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:4/0/physics_layer_0/angular_velocity = 0.0 +21:4/0 = 0 +21:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:4/0/physics_layer_0/angular_velocity = 0.0 +22:4/0 = 0 +22:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:4/0/physics_layer_0/angular_velocity = 0.0 +23:4/0 = 0 +23:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:4/0/physics_layer_0/angular_velocity = 0.0 +24:4/0 = 0 +24:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:4/0/physics_layer_0/angular_velocity = 0.0 +25:4/0 = 0 +25:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:4/0/physics_layer_0/angular_velocity = 0.0 +26:4/0 = 0 +26:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:4/0/physics_layer_0/angular_velocity = 0.0 +27:4/0 = 0 +27:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:4/0/physics_layer_0/angular_velocity = 0.0 +28:4/0 = 0 +28:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:4/0/physics_layer_0/angular_velocity = 0.0 +29:4/0 = 0 +29:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:4/0/physics_layer_0/angular_velocity = 0.0 +30:4/0 = 0 +30:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:4/0/physics_layer_0/angular_velocity = 0.0 +31:4/0 = 0 +31:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:4/0/physics_layer_0/angular_velocity = 0.0 +32:4/0 = 0 +32:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:4/0/physics_layer_0/angular_velocity = 0.0 +33:4/0 = 0 +33:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:4/0/physics_layer_0/angular_velocity = 0.0 +34:4/0 = 0 +34:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:4/0/physics_layer_0/angular_velocity = 0.0 +35:4/0 = 0 +35:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:4/0/physics_layer_0/angular_velocity = 0.0 +36:4/0 = 0 +36:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:4/0/physics_layer_0/angular_velocity = 0.0 +37:4/0 = 0 +37:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:4/0/physics_layer_0/angular_velocity = 0.0 +38:4/0 = 0 +38:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:4/0/physics_layer_0/angular_velocity = 0.0 +39:4/0 = 0 +39:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:4/0/physics_layer_0/angular_velocity = 0.0 +40:4/0 = 0 +40:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:4/0/physics_layer_0/angular_velocity = 0.0 +41:4/0 = 0 +41:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:4/0/physics_layer_0/angular_velocity = 0.0 +42:4/0 = 0 +42:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:4/0/physics_layer_0/angular_velocity = 0.0 +43:4/0 = 0 +43:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:4/0/physics_layer_0/angular_velocity = 0.0 +44:4/0 = 0 +44:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:4/0/physics_layer_0/angular_velocity = 0.0 +45:4/0 = 0 +45:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:4/0/physics_layer_0/angular_velocity = 0.0 +46:4/0 = 0 +46:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:4/0/physics_layer_0/angular_velocity = 0.0 +47:4/0 = 0 +47:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:4/0/physics_layer_0/angular_velocity = 0.0 +48:4/0 = 0 +48:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:4/0/physics_layer_0/angular_velocity = 0.0 +0:5/0 = 0 +0:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:5/0/physics_layer_0/angular_velocity = 0.0 +1:5/0 = 0 +1:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:5/0/physics_layer_0/angular_velocity = 0.0 +2:5/0 = 0 +2:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:5/0/physics_layer_0/angular_velocity = 0.0 +3:5/0 = 0 +3:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:5/0/physics_layer_0/angular_velocity = 0.0 +4:5/0 = 0 +4:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:5/0/physics_layer_0/angular_velocity = 0.0 +5:5/0 = 0 +5:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:5/0/physics_layer_0/angular_velocity = 0.0 +6:5/0 = 0 +6:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:5/0/physics_layer_0/angular_velocity = 0.0 +7:5/0 = 0 +7:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:5/0/physics_layer_0/angular_velocity = 0.0 +8:5/0 = 0 +8:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:5/0/physics_layer_0/angular_velocity = 0.0 +9:5/0 = 0 +9:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:5/0/physics_layer_0/angular_velocity = 0.0 +10:5/0 = 0 +10:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:5/0/physics_layer_0/angular_velocity = 0.0 +11:5/0 = 0 +11:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:5/0/physics_layer_0/angular_velocity = 0.0 +12:5/0 = 0 +12:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:5/0/physics_layer_0/angular_velocity = 0.0 +13:5/0 = 0 +13:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:5/0/physics_layer_0/angular_velocity = 0.0 +14:5/0 = 0 +14:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:5/0/physics_layer_0/angular_velocity = 0.0 +15:5/0 = 0 +15:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:5/0/physics_layer_0/angular_velocity = 0.0 +16:5/0 = 0 +16:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:5/0/physics_layer_0/angular_velocity = 0.0 +17:5/0 = 0 +17:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:5/0/physics_layer_0/angular_velocity = 0.0 +18:5/0 = 0 +18:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:5/0/physics_layer_0/angular_velocity = 0.0 +19:5/0 = 0 +19:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:5/0/physics_layer_0/angular_velocity = 0.0 +20:5/0 = 0 +20:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:5/0/physics_layer_0/angular_velocity = 0.0 +21:5/0 = 0 +21:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:5/0/physics_layer_0/angular_velocity = 0.0 +22:5/0 = 0 +22:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:5/0/physics_layer_0/angular_velocity = 0.0 +23:5/0 = 0 +23:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:5/0/physics_layer_0/angular_velocity = 0.0 +24:5/0 = 0 +24:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:5/0/physics_layer_0/angular_velocity = 0.0 +25:5/0 = 0 +25:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:5/0/physics_layer_0/angular_velocity = 0.0 +26:5/0 = 0 +26:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:5/0/physics_layer_0/angular_velocity = 0.0 +27:5/0 = 0 +27:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:5/0/physics_layer_0/angular_velocity = 0.0 +28:5/0 = 0 +28:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:5/0/physics_layer_0/angular_velocity = 0.0 +29:5/0 = 0 +29:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:5/0/physics_layer_0/angular_velocity = 0.0 +30:5/0 = 0 +30:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:5/0/physics_layer_0/angular_velocity = 0.0 +31:5/0 = 0 +31:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:5/0/physics_layer_0/angular_velocity = 0.0 +32:5/0 = 0 +32:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:5/0/physics_layer_0/angular_velocity = 0.0 +33:5/0 = 0 +33:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:5/0/physics_layer_0/angular_velocity = 0.0 +34:5/0 = 0 +34:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:5/0/physics_layer_0/angular_velocity = 0.0 +35:5/0 = 0 +35:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:5/0/physics_layer_0/angular_velocity = 0.0 +36:5/0 = 0 +36:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:5/0/physics_layer_0/angular_velocity = 0.0 +37:5/0 = 0 +37:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:5/0/physics_layer_0/angular_velocity = 0.0 +38:5/0 = 0 +38:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:5/0/physics_layer_0/angular_velocity = 0.0 +39:5/0 = 0 +39:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:5/0/physics_layer_0/angular_velocity = 0.0 +40:5/0 = 0 +40:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:5/0/physics_layer_0/angular_velocity = 0.0 +41:5/0 = 0 +41:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:5/0/physics_layer_0/angular_velocity = 0.0 +42:5/0 = 0 +42:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:5/0/physics_layer_0/angular_velocity = 0.0 +43:5/0 = 0 +43:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:5/0/physics_layer_0/angular_velocity = 0.0 +44:5/0 = 0 +44:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:5/0/physics_layer_0/angular_velocity = 0.0 +45:5/0 = 0 +45:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:5/0/physics_layer_0/angular_velocity = 0.0 +46:5/0 = 0 +46:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:5/0/physics_layer_0/angular_velocity = 0.0 +47:5/0 = 0 +47:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:5/0/physics_layer_0/angular_velocity = 0.0 +48:5/0 = 0 +48:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:5/0/physics_layer_0/angular_velocity = 0.0 +0:6/0 = 0 +0:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:6/0/physics_layer_0/angular_velocity = 0.0 +1:6/0 = 0 +1:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:6/0/physics_layer_0/angular_velocity = 0.0 +2:6/0 = 0 +2:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:6/0/physics_layer_0/angular_velocity = 0.0 +3:6/0 = 0 +3:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:6/0/physics_layer_0/angular_velocity = 0.0 +4:6/0 = 0 +4:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:6/0/physics_layer_0/angular_velocity = 0.0 +5:6/0 = 0 +5:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:6/0/physics_layer_0/angular_velocity = 0.0 +6:6/0 = 0 +6:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:6/0/physics_layer_0/angular_velocity = 0.0 +7:6/0 = 0 +7:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:6/0/physics_layer_0/angular_velocity = 0.0 +8:6/0 = 0 +8:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:6/0/physics_layer_0/angular_velocity = 0.0 +9:6/0 = 0 +9:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:6/0/physics_layer_0/angular_velocity = 0.0 +10:6/0 = 0 +10:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:6/0/physics_layer_0/angular_velocity = 0.0 +11:6/0 = 0 +11:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:6/0/physics_layer_0/angular_velocity = 0.0 +12:6/0 = 0 +12:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:6/0/physics_layer_0/angular_velocity = 0.0 +13:6/0 = 0 +13:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:6/0/physics_layer_0/angular_velocity = 0.0 +14:6/0 = 0 +14:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:6/0/physics_layer_0/angular_velocity = 0.0 +15:6/0 = 0 +15:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:6/0/physics_layer_0/angular_velocity = 0.0 +16:6/0 = 0 +16:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:6/0/physics_layer_0/angular_velocity = 0.0 +17:6/0 = 0 +17:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:6/0/physics_layer_0/angular_velocity = 0.0 +18:6/0 = 0 +18:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:6/0/physics_layer_0/angular_velocity = 0.0 +19:6/0 = 0 +19:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:6/0/physics_layer_0/angular_velocity = 0.0 +20:6/0 = 0 +20:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:6/0/physics_layer_0/angular_velocity = 0.0 +21:6/0 = 0 +21:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:6/0/physics_layer_0/angular_velocity = 0.0 +22:6/0 = 0 +22:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:6/0/physics_layer_0/angular_velocity = 0.0 +23:6/0 = 0 +23:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:6/0/physics_layer_0/angular_velocity = 0.0 +24:6/0 = 0 +24:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:6/0/physics_layer_0/angular_velocity = 0.0 +25:6/0 = 0 +25:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:6/0/physics_layer_0/angular_velocity = 0.0 +26:6/0 = 0 +26:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:6/0/physics_layer_0/angular_velocity = 0.0 +27:6/0 = 0 +27:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:6/0/physics_layer_0/angular_velocity = 0.0 +28:6/0 = 0 +28:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:6/0/physics_layer_0/angular_velocity = 0.0 +29:6/0 = 0 +29:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:6/0/physics_layer_0/angular_velocity = 0.0 +30:6/0 = 0 +30:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:6/0/physics_layer_0/angular_velocity = 0.0 +31:6/0 = 0 +31:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:6/0/physics_layer_0/angular_velocity = 0.0 +32:6/0 = 0 +32:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:6/0/physics_layer_0/angular_velocity = 0.0 +33:6/0 = 0 +33:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:6/0/physics_layer_0/angular_velocity = 0.0 +34:6/0 = 0 +34:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:6/0/physics_layer_0/angular_velocity = 0.0 +35:6/0 = 0 +35:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:6/0/physics_layer_0/angular_velocity = 0.0 +36:6/0 = 0 +36:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:6/0/physics_layer_0/angular_velocity = 0.0 +37:6/0 = 0 +37:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:6/0/physics_layer_0/angular_velocity = 0.0 +38:6/0 = 0 +38:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:6/0/physics_layer_0/angular_velocity = 0.0 +39:6/0 = 0 +39:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:6/0/physics_layer_0/angular_velocity = 0.0 +40:6/0 = 0 +40:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:6/0/physics_layer_0/angular_velocity = 0.0 +41:6/0 = 0 +41:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:6/0/physics_layer_0/angular_velocity = 0.0 +42:6/0 = 0 +42:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:6/0/physics_layer_0/angular_velocity = 0.0 +43:6/0 = 0 +43:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:6/0/physics_layer_0/angular_velocity = 0.0 +44:6/0 = 0 +44:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:6/0/physics_layer_0/angular_velocity = 0.0 +45:6/0 = 0 +45:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:6/0/physics_layer_0/angular_velocity = 0.0 +46:6/0 = 0 +46:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:6/0/physics_layer_0/angular_velocity = 0.0 +47:6/0 = 0 +47:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:6/0/physics_layer_0/angular_velocity = 0.0 +48:6/0 = 0 +48:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:6/0/physics_layer_0/angular_velocity = 0.0 +0:7/0 = 0 +0:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:7/0/physics_layer_0/angular_velocity = 0.0 +1:7/0 = 0 +1:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:7/0/physics_layer_0/angular_velocity = 0.0 +2:7/0 = 0 +2:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:7/0/physics_layer_0/angular_velocity = 0.0 +3:7/0 = 0 +3:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:7/0/physics_layer_0/angular_velocity = 0.0 +4:7/0 = 0 +4:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:7/0/physics_layer_0/angular_velocity = 0.0 +5:7/0 = 0 +5:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:7/0/physics_layer_0/angular_velocity = 0.0 +6:7/0 = 0 +6:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:7/0/physics_layer_0/angular_velocity = 0.0 +7:7/0 = 0 +7:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:7/0/physics_layer_0/angular_velocity = 0.0 +8:7/0 = 0 +8:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:7/0/physics_layer_0/angular_velocity = 0.0 +9:7/0 = 0 +9:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:7/0/physics_layer_0/angular_velocity = 0.0 +10:7/0 = 0 +10:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:7/0/physics_layer_0/angular_velocity = 0.0 +11:7/0 = 0 +11:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:7/0/physics_layer_0/angular_velocity = 0.0 +12:7/0 = 0 +12:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:7/0/physics_layer_0/angular_velocity = 0.0 +13:7/0 = 0 +13:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:7/0/physics_layer_0/angular_velocity = 0.0 +14:7/0 = 0 +14:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:7/0/physics_layer_0/angular_velocity = 0.0 +15:7/0 = 0 +15:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:7/0/physics_layer_0/angular_velocity = 0.0 +16:7/0 = 0 +16:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:7/0/physics_layer_0/angular_velocity = 0.0 +17:7/0 = 0 +17:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:7/0/physics_layer_0/angular_velocity = 0.0 +18:7/0 = 0 +18:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:7/0/physics_layer_0/angular_velocity = 0.0 +19:7/0 = 0 +19:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:7/0/physics_layer_0/angular_velocity = 0.0 +20:7/0 = 0 +20:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:7/0/physics_layer_0/angular_velocity = 0.0 +21:7/0 = 0 +21:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:7/0/physics_layer_0/angular_velocity = 0.0 +22:7/0 = 0 +22:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:7/0/physics_layer_0/angular_velocity = 0.0 +23:7/0 = 0 +23:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:7/0/physics_layer_0/angular_velocity = 0.0 +24:7/0 = 0 +24:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:7/0/physics_layer_0/angular_velocity = 0.0 +25:7/0 = 0 +25:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:7/0/physics_layer_0/angular_velocity = 0.0 +26:7/0 = 0 +26:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:7/0/physics_layer_0/angular_velocity = 0.0 +27:7/0 = 0 +27:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:7/0/physics_layer_0/angular_velocity = 0.0 +28:7/0 = 0 +28:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:7/0/physics_layer_0/angular_velocity = 0.0 +29:7/0 = 0 +29:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:7/0/physics_layer_0/angular_velocity = 0.0 +30:7/0 = 0 +30:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:7/0/physics_layer_0/angular_velocity = 0.0 +31:7/0 = 0 +31:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:7/0/physics_layer_0/angular_velocity = 0.0 +32:7/0 = 0 +32:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:7/0/physics_layer_0/angular_velocity = 0.0 +33:7/0 = 0 +33:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:7/0/physics_layer_0/angular_velocity = 0.0 +34:7/0 = 0 +34:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:7/0/physics_layer_0/angular_velocity = 0.0 +35:7/0 = 0 +35:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:7/0/physics_layer_0/angular_velocity = 0.0 +36:7/0 = 0 +36:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:7/0/physics_layer_0/angular_velocity = 0.0 +37:7/0 = 0 +37:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:7/0/physics_layer_0/angular_velocity = 0.0 +38:7/0 = 0 +38:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:7/0/physics_layer_0/angular_velocity = 0.0 +39:7/0 = 0 +39:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:7/0/physics_layer_0/angular_velocity = 0.0 +40:7/0 = 0 +40:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:7/0/physics_layer_0/angular_velocity = 0.0 +41:7/0 = 0 +41:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:7/0/physics_layer_0/angular_velocity = 0.0 +42:7/0 = 0 +42:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:7/0/physics_layer_0/angular_velocity = 0.0 +43:7/0 = 0 +43:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:7/0/physics_layer_0/angular_velocity = 0.0 +44:7/0 = 0 +44:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:7/0/physics_layer_0/angular_velocity = 0.0 +45:7/0 = 0 +45:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:7/0/physics_layer_0/angular_velocity = 0.0 +46:7/0 = 0 +46:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:7/0/physics_layer_0/angular_velocity = 0.0 +47:7/0 = 0 +47:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:7/0/physics_layer_0/angular_velocity = 0.0 +48:7/0 = 0 +48:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:7/0/physics_layer_0/angular_velocity = 0.0 +0:8/0 = 0 +0:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:8/0/physics_layer_0/angular_velocity = 0.0 +1:8/0 = 0 +1:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:8/0/physics_layer_0/angular_velocity = 0.0 +2:8/0 = 0 +2:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:8/0/physics_layer_0/angular_velocity = 0.0 +3:8/0 = 0 +3:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:8/0/physics_layer_0/angular_velocity = 0.0 +4:8/0 = 0 +4:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:8/0/physics_layer_0/angular_velocity = 0.0 +5:8/0 = 0 +5:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:8/0/physics_layer_0/angular_velocity = 0.0 +6:8/0 = 0 +6:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:8/0/physics_layer_0/angular_velocity = 0.0 +7:8/0 = 0 +7:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:8/0/physics_layer_0/angular_velocity = 0.0 +8:8/0 = 0 +8:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:8/0/physics_layer_0/angular_velocity = 0.0 +9:8/0 = 0 +9:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:8/0/physics_layer_0/angular_velocity = 0.0 +10:8/0 = 0 +10:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:8/0/physics_layer_0/angular_velocity = 0.0 +11:8/0 = 0 +11:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:8/0/physics_layer_0/angular_velocity = 0.0 +12:8/0 = 0 +12:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:8/0/physics_layer_0/angular_velocity = 0.0 +13:8/0 = 0 +13:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:8/0/physics_layer_0/angular_velocity = 0.0 +14:8/0 = 0 +14:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:8/0/physics_layer_0/angular_velocity = 0.0 +15:8/0 = 0 +15:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:8/0/physics_layer_0/angular_velocity = 0.0 +16:8/0 = 0 +16:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:8/0/physics_layer_0/angular_velocity = 0.0 +17:8/0 = 0 +17:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:8/0/physics_layer_0/angular_velocity = 0.0 +18:8/0 = 0 +18:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:8/0/physics_layer_0/angular_velocity = 0.0 +19:8/0 = 0 +19:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:8/0/physics_layer_0/angular_velocity = 0.0 +20:8/0 = 0 +20:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:8/0/physics_layer_0/angular_velocity = 0.0 +21:8/0 = 0 +21:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:8/0/physics_layer_0/angular_velocity = 0.0 +22:8/0 = 0 +22:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:8/0/physics_layer_0/angular_velocity = 0.0 +23:8/0 = 0 +23:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:8/0/physics_layer_0/angular_velocity = 0.0 +24:8/0 = 0 +24:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:8/0/physics_layer_0/angular_velocity = 0.0 +25:8/0 = 0 +25:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:8/0/physics_layer_0/angular_velocity = 0.0 +26:8/0 = 0 +26:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:8/0/physics_layer_0/angular_velocity = 0.0 +27:8/0 = 0 +27:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:8/0/physics_layer_0/angular_velocity = 0.0 +28:8/0 = 0 +28:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:8/0/physics_layer_0/angular_velocity = 0.0 +29:8/0 = 0 +29:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:8/0/physics_layer_0/angular_velocity = 0.0 +30:8/0 = 0 +30:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:8/0/physics_layer_0/angular_velocity = 0.0 +31:8/0 = 0 +31:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:8/0/physics_layer_0/angular_velocity = 0.0 +32:8/0 = 0 +32:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:8/0/physics_layer_0/angular_velocity = 0.0 +33:8/0 = 0 +33:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:8/0/physics_layer_0/angular_velocity = 0.0 +34:8/0 = 0 +34:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:8/0/physics_layer_0/angular_velocity = 0.0 +35:8/0 = 0 +35:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:8/0/physics_layer_0/angular_velocity = 0.0 +36:8/0 = 0 +36:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:8/0/physics_layer_0/angular_velocity = 0.0 +37:8/0 = 0 +37:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:8/0/physics_layer_0/angular_velocity = 0.0 +38:8/0 = 0 +38:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:8/0/physics_layer_0/angular_velocity = 0.0 +39:8/0 = 0 +39:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:8/0/physics_layer_0/angular_velocity = 0.0 +40:8/0 = 0 +40:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:8/0/physics_layer_0/angular_velocity = 0.0 +41:8/0 = 0 +41:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:8/0/physics_layer_0/angular_velocity = 0.0 +42:8/0 = 0 +42:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:8/0/physics_layer_0/angular_velocity = 0.0 +43:8/0 = 0 +43:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:8/0/physics_layer_0/angular_velocity = 0.0 +44:8/0 = 0 +44:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:8/0/physics_layer_0/angular_velocity = 0.0 +45:8/0 = 0 +45:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:8/0/physics_layer_0/angular_velocity = 0.0 +46:8/0 = 0 +46:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:8/0/physics_layer_0/angular_velocity = 0.0 +47:8/0 = 0 +47:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:8/0/physics_layer_0/angular_velocity = 0.0 +48:8/0 = 0 +48:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:8/0/physics_layer_0/angular_velocity = 0.0 +0:9/0 = 0 +0:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:9/0/physics_layer_0/angular_velocity = 0.0 +1:9/0 = 0 +1:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:9/0/physics_layer_0/angular_velocity = 0.0 +2:9/0 = 0 +2:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:9/0/physics_layer_0/angular_velocity = 0.0 +3:9/0 = 0 +3:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:9/0/physics_layer_0/angular_velocity = 0.0 +4:9/0 = 0 +4:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:9/0/physics_layer_0/angular_velocity = 0.0 +5:9/0 = 0 +5:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:9/0/physics_layer_0/angular_velocity = 0.0 +6:9/0 = 0 +6:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:9/0/physics_layer_0/angular_velocity = 0.0 +7:9/0 = 0 +7:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:9/0/physics_layer_0/angular_velocity = 0.0 +8:9/0 = 0 +8:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:9/0/physics_layer_0/angular_velocity = 0.0 +9:9/0 = 0 +9:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:9/0/physics_layer_0/angular_velocity = 0.0 +10:9/0 = 0 +10:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:9/0/physics_layer_0/angular_velocity = 0.0 +11:9/0 = 0 +11:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:9/0/physics_layer_0/angular_velocity = 0.0 +12:9/0 = 0 +12:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:9/0/physics_layer_0/angular_velocity = 0.0 +13:9/0 = 0 +13:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:9/0/physics_layer_0/angular_velocity = 0.0 +14:9/0 = 0 +14:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:9/0/physics_layer_0/angular_velocity = 0.0 +15:9/0 = 0 +15:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:9/0/physics_layer_0/angular_velocity = 0.0 +16:9/0 = 0 +16:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:9/0/physics_layer_0/angular_velocity = 0.0 +17:9/0 = 0 +17:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:9/0/physics_layer_0/angular_velocity = 0.0 +18:9/0 = 0 +18:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:9/0/physics_layer_0/angular_velocity = 0.0 +19:9/0 = 0 +19:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:9/0/physics_layer_0/angular_velocity = 0.0 +20:9/0 = 0 +20:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:9/0/physics_layer_0/angular_velocity = 0.0 +21:9/0 = 0 +21:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:9/0/physics_layer_0/angular_velocity = 0.0 +22:9/0 = 0 +22:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:9/0/physics_layer_0/angular_velocity = 0.0 +23:9/0 = 0 +23:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:9/0/physics_layer_0/angular_velocity = 0.0 +24:9/0 = 0 +24:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:9/0/physics_layer_0/angular_velocity = 0.0 +25:9/0 = 0 +25:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:9/0/physics_layer_0/angular_velocity = 0.0 +26:9/0 = 0 +26:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:9/0/physics_layer_0/angular_velocity = 0.0 +27:9/0 = 0 +27:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:9/0/physics_layer_0/angular_velocity = 0.0 +28:9/0 = 0 +28:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:9/0/physics_layer_0/angular_velocity = 0.0 +29:9/0 = 0 +29:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:9/0/physics_layer_0/angular_velocity = 0.0 +30:9/0 = 0 +30:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:9/0/physics_layer_0/angular_velocity = 0.0 +31:9/0 = 0 +31:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:9/0/physics_layer_0/angular_velocity = 0.0 +32:9/0 = 0 +32:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:9/0/physics_layer_0/angular_velocity = 0.0 +33:9/0 = 0 +33:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:9/0/physics_layer_0/angular_velocity = 0.0 +34:9/0 = 0 +34:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:9/0/physics_layer_0/angular_velocity = 0.0 +35:9/0 = 0 +35:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:9/0/physics_layer_0/angular_velocity = 0.0 +36:9/0 = 0 +36:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:9/0/physics_layer_0/angular_velocity = 0.0 +37:9/0 = 0 +37:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:9/0/physics_layer_0/angular_velocity = 0.0 +38:9/0 = 0 +38:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:9/0/physics_layer_0/angular_velocity = 0.0 +39:9/0 = 0 +39:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:9/0/physics_layer_0/angular_velocity = 0.0 +40:9/0 = 0 +40:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:9/0/physics_layer_0/angular_velocity = 0.0 +41:9/0 = 0 +41:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:9/0/physics_layer_0/angular_velocity = 0.0 +42:9/0 = 0 +42:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:9/0/physics_layer_0/angular_velocity = 0.0 +43:9/0 = 0 +43:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:9/0/physics_layer_0/angular_velocity = 0.0 +44:9/0 = 0 +44:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:9/0/physics_layer_0/angular_velocity = 0.0 +45:9/0 = 0 +45:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:9/0/physics_layer_0/angular_velocity = 0.0 +46:9/0 = 0 +46:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:9/0/physics_layer_0/angular_velocity = 0.0 +47:9/0 = 0 +47:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:9/0/physics_layer_0/angular_velocity = 0.0 +48:9/0 = 0 +48:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:9/0/physics_layer_0/angular_velocity = 0.0 +0:10/0 = 0 +0:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:10/0/physics_layer_0/angular_velocity = 0.0 +1:10/0 = 0 +1:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:10/0/physics_layer_0/angular_velocity = 0.0 +2:10/0 = 0 +2:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:10/0/physics_layer_0/angular_velocity = 0.0 +3:10/0 = 0 +3:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:10/0/physics_layer_0/angular_velocity = 0.0 +4:10/0 = 0 +4:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:10/0/physics_layer_0/angular_velocity = 0.0 +5:10/0 = 0 +5:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:10/0/physics_layer_0/angular_velocity = 0.0 +6:10/0 = 0 +6:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:10/0/physics_layer_0/angular_velocity = 0.0 +7:10/0 = 0 +7:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:10/0/physics_layer_0/angular_velocity = 0.0 +8:10/0 = 0 +8:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:10/0/physics_layer_0/angular_velocity = 0.0 +9:10/0 = 0 +9:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:10/0/physics_layer_0/angular_velocity = 0.0 +10:10/0 = 0 +10:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:10/0/physics_layer_0/angular_velocity = 0.0 +11:10/0 = 0 +11:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:10/0/physics_layer_0/angular_velocity = 0.0 +12:10/0 = 0 +12:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:10/0/physics_layer_0/angular_velocity = 0.0 +13:10/0 = 0 +13:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:10/0/physics_layer_0/angular_velocity = 0.0 +14:10/0 = 0 +14:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:10/0/physics_layer_0/angular_velocity = 0.0 +15:10/0 = 0 +15:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:10/0/physics_layer_0/angular_velocity = 0.0 +16:10/0 = 0 +16:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:10/0/physics_layer_0/angular_velocity = 0.0 +17:10/0 = 0 +17:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:10/0/physics_layer_0/angular_velocity = 0.0 +18:10/0 = 0 +18:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:10/0/physics_layer_0/angular_velocity = 0.0 +19:10/0 = 0 +19:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:10/0/physics_layer_0/angular_velocity = 0.0 +20:10/0 = 0 +20:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:10/0/physics_layer_0/angular_velocity = 0.0 +21:10/0 = 0 +21:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:10/0/physics_layer_0/angular_velocity = 0.0 +22:10/0 = 0 +22:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:10/0/physics_layer_0/angular_velocity = 0.0 +23:10/0 = 0 +23:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:10/0/physics_layer_0/angular_velocity = 0.0 +24:10/0 = 0 +24:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:10/0/physics_layer_0/angular_velocity = 0.0 +25:10/0 = 0 +25:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:10/0/physics_layer_0/angular_velocity = 0.0 +26:10/0 = 0 +26:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:10/0/physics_layer_0/angular_velocity = 0.0 +27:10/0 = 0 +27:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:10/0/physics_layer_0/angular_velocity = 0.0 +28:10/0 = 0 +28:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:10/0/physics_layer_0/angular_velocity = 0.0 +29:10/0 = 0 +29:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:10/0/physics_layer_0/angular_velocity = 0.0 +30:10/0 = 0 +30:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:10/0/physics_layer_0/angular_velocity = 0.0 +31:10/0 = 0 +31:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:10/0/physics_layer_0/angular_velocity = 0.0 +32:10/0 = 0 +32:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:10/0/physics_layer_0/angular_velocity = 0.0 +33:10/0 = 0 +33:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:10/0/physics_layer_0/angular_velocity = 0.0 +34:10/0 = 0 +34:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:10/0/physics_layer_0/angular_velocity = 0.0 +35:10/0 = 0 +35:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:10/0/physics_layer_0/angular_velocity = 0.0 +36:10/0 = 0 +36:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:10/0/physics_layer_0/angular_velocity = 0.0 +37:10/0 = 0 +37:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:10/0/physics_layer_0/angular_velocity = 0.0 +38:10/0 = 0 +38:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:10/0/physics_layer_0/angular_velocity = 0.0 +39:10/0 = 0 +39:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:10/0/physics_layer_0/angular_velocity = 0.0 +40:10/0 = 0 +40:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:10/0/physics_layer_0/angular_velocity = 0.0 +41:10/0 = 0 +41:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:10/0/physics_layer_0/angular_velocity = 0.0 +42:10/0 = 0 +42:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:10/0/physics_layer_0/angular_velocity = 0.0 +43:10/0 = 0 +43:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:10/0/physics_layer_0/angular_velocity = 0.0 +44:10/0 = 0 +44:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:10/0/physics_layer_0/angular_velocity = 0.0 +45:10/0 = 0 +45:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:10/0/physics_layer_0/angular_velocity = 0.0 +46:10/0 = 0 +46:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:10/0/physics_layer_0/angular_velocity = 0.0 +47:10/0 = 0 +47:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:10/0/physics_layer_0/angular_velocity = 0.0 +48:10/0 = 0 +48:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:10/0/physics_layer_0/angular_velocity = 0.0 +0:11/0 = 0 +0:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:11/0/physics_layer_0/angular_velocity = 0.0 +1:11/0 = 0 +1:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:11/0/physics_layer_0/angular_velocity = 0.0 +2:11/0 = 0 +2:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:11/0/physics_layer_0/angular_velocity = 0.0 +3:11/0 = 0 +3:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:11/0/physics_layer_0/angular_velocity = 0.0 +4:11/0 = 0 +4:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:11/0/physics_layer_0/angular_velocity = 0.0 +5:11/0 = 0 +5:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:11/0/physics_layer_0/angular_velocity = 0.0 +6:11/0 = 0 +6:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:11/0/physics_layer_0/angular_velocity = 0.0 +7:11/0 = 0 +7:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:11/0/physics_layer_0/angular_velocity = 0.0 +8:11/0 = 0 +8:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:11/0/physics_layer_0/angular_velocity = 0.0 +9:11/0 = 0 +9:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:11/0/physics_layer_0/angular_velocity = 0.0 +10:11/0 = 0 +10:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:11/0/physics_layer_0/angular_velocity = 0.0 +11:11/0 = 0 +11:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:11/0/physics_layer_0/angular_velocity = 0.0 +12:11/0 = 0 +12:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:11/0/physics_layer_0/angular_velocity = 0.0 +13:11/0 = 0 +13:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:11/0/physics_layer_0/angular_velocity = 0.0 +14:11/0 = 0 +14:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:11/0/physics_layer_0/angular_velocity = 0.0 +15:11/0 = 0 +15:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:11/0/physics_layer_0/angular_velocity = 0.0 +16:11/0 = 0 +16:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:11/0/physics_layer_0/angular_velocity = 0.0 +17:11/0 = 0 +17:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:11/0/physics_layer_0/angular_velocity = 0.0 +18:11/0 = 0 +18:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:11/0/physics_layer_0/angular_velocity = 0.0 +19:11/0 = 0 +19:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:11/0/physics_layer_0/angular_velocity = 0.0 +20:11/0 = 0 +20:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:11/0/physics_layer_0/angular_velocity = 0.0 +21:11/0 = 0 +21:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:11/0/physics_layer_0/angular_velocity = 0.0 +22:11/0 = 0 +22:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:11/0/physics_layer_0/angular_velocity = 0.0 +23:11/0 = 0 +23:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:11/0/physics_layer_0/angular_velocity = 0.0 +24:11/0 = 0 +24:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:11/0/physics_layer_0/angular_velocity = 0.0 +25:11/0 = 0 +25:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:11/0/physics_layer_0/angular_velocity = 0.0 +26:11/0 = 0 +26:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:11/0/physics_layer_0/angular_velocity = 0.0 +27:11/0 = 0 +27:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:11/0/physics_layer_0/angular_velocity = 0.0 +28:11/0 = 0 +28:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:11/0/physics_layer_0/angular_velocity = 0.0 +29:11/0 = 0 +29:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:11/0/physics_layer_0/angular_velocity = 0.0 +30:11/0 = 0 +30:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:11/0/physics_layer_0/angular_velocity = 0.0 +31:11/0 = 0 +31:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:11/0/physics_layer_0/angular_velocity = 0.0 +32:11/0 = 0 +32:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:11/0/physics_layer_0/angular_velocity = 0.0 +33:11/0 = 0 +33:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:11/0/physics_layer_0/angular_velocity = 0.0 +34:11/0 = 0 +34:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:11/0/physics_layer_0/angular_velocity = 0.0 +35:11/0 = 0 +35:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:11/0/physics_layer_0/angular_velocity = 0.0 +36:11/0 = 0 +36:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:11/0/physics_layer_0/angular_velocity = 0.0 +37:11/0 = 0 +37:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:11/0/physics_layer_0/angular_velocity = 0.0 +38:11/0 = 0 +38:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:11/0/physics_layer_0/angular_velocity = 0.0 +39:11/0 = 0 +39:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:11/0/physics_layer_0/angular_velocity = 0.0 +40:11/0 = 0 +40:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:11/0/physics_layer_0/angular_velocity = 0.0 +41:11/0 = 0 +41:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:11/0/physics_layer_0/angular_velocity = 0.0 +42:11/0 = 0 +42:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:11/0/physics_layer_0/angular_velocity = 0.0 +43:11/0 = 0 +43:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:11/0/physics_layer_0/angular_velocity = 0.0 +44:11/0 = 0 +44:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:11/0/physics_layer_0/angular_velocity = 0.0 +45:11/0 = 0 +45:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:11/0/physics_layer_0/angular_velocity = 0.0 +46:11/0 = 0 +46:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:11/0/physics_layer_0/angular_velocity = 0.0 +47:11/0 = 0 +47:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:11/0/physics_layer_0/angular_velocity = 0.0 +48:11/0 = 0 +48:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:11/0/physics_layer_0/angular_velocity = 0.0 +0:12/0 = 0 +0:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:12/0/physics_layer_0/angular_velocity = 0.0 +1:12/0 = 0 +1:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:12/0/physics_layer_0/angular_velocity = 0.0 +2:12/0 = 0 +2:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:12/0/physics_layer_0/angular_velocity = 0.0 +3:12/0 = 0 +3:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:12/0/physics_layer_0/angular_velocity = 0.0 +4:12/0 = 0 +4:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:12/0/physics_layer_0/angular_velocity = 0.0 +5:12/0 = 0 +5:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:12/0/physics_layer_0/angular_velocity = 0.0 +6:12/0 = 0 +6:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:12/0/physics_layer_0/angular_velocity = 0.0 +7:12/0 = 0 +7:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:12/0/physics_layer_0/angular_velocity = 0.0 +8:12/0 = 0 +8:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:12/0/physics_layer_0/angular_velocity = 0.0 +9:12/0 = 0 +9:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:12/0/physics_layer_0/angular_velocity = 0.0 +10:12/0 = 0 +10:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:12/0/physics_layer_0/angular_velocity = 0.0 +11:12/0 = 0 +11:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:12/0/physics_layer_0/angular_velocity = 0.0 +12:12/0 = 0 +12:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:12/0/physics_layer_0/angular_velocity = 0.0 +13:12/0 = 0 +13:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:12/0/physics_layer_0/angular_velocity = 0.0 +14:12/0 = 0 +14:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:12/0/physics_layer_0/angular_velocity = 0.0 +15:12/0 = 0 +15:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:12/0/physics_layer_0/angular_velocity = 0.0 +16:12/0 = 0 +16:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:12/0/physics_layer_0/angular_velocity = 0.0 +17:12/0 = 0 +17:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:12/0/physics_layer_0/angular_velocity = 0.0 +18:12/0 = 0 +18:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:12/0/physics_layer_0/angular_velocity = 0.0 +19:12/0 = 0 +19:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:12/0/physics_layer_0/angular_velocity = 0.0 +20:12/0 = 0 +20:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:12/0/physics_layer_0/angular_velocity = 0.0 +21:12/0 = 0 +21:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:12/0/physics_layer_0/angular_velocity = 0.0 +22:12/0 = 0 +22:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:12/0/physics_layer_0/angular_velocity = 0.0 +23:12/0 = 0 +23:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:12/0/physics_layer_0/angular_velocity = 0.0 +24:12/0 = 0 +24:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:12/0/physics_layer_0/angular_velocity = 0.0 +25:12/0 = 0 +25:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:12/0/physics_layer_0/angular_velocity = 0.0 +26:12/0 = 0 +26:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:12/0/physics_layer_0/angular_velocity = 0.0 +27:12/0 = 0 +27:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:12/0/physics_layer_0/angular_velocity = 0.0 +28:12/0 = 0 +28:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:12/0/physics_layer_0/angular_velocity = 0.0 +29:12/0 = 0 +29:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:12/0/physics_layer_0/angular_velocity = 0.0 +30:12/0 = 0 +30:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:12/0/physics_layer_0/angular_velocity = 0.0 +31:12/0 = 0 +31:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:12/0/physics_layer_0/angular_velocity = 0.0 +32:12/0 = 0 +32:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:12/0/physics_layer_0/angular_velocity = 0.0 +33:12/0 = 0 +33:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:12/0/physics_layer_0/angular_velocity = 0.0 +34:12/0 = 0 +34:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:12/0/physics_layer_0/angular_velocity = 0.0 +35:12/0 = 0 +35:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:12/0/physics_layer_0/angular_velocity = 0.0 +36:12/0 = 0 +36:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:12/0/physics_layer_0/angular_velocity = 0.0 +37:12/0 = 0 +37:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:12/0/physics_layer_0/angular_velocity = 0.0 +38:12/0 = 0 +38:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:12/0/physics_layer_0/angular_velocity = 0.0 +39:12/0 = 0 +39:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:12/0/physics_layer_0/angular_velocity = 0.0 +40:12/0 = 0 +40:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:12/0/physics_layer_0/angular_velocity = 0.0 +41:12/0 = 0 +41:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:12/0/physics_layer_0/angular_velocity = 0.0 +42:12/0 = 0 +42:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:12/0/physics_layer_0/angular_velocity = 0.0 +43:12/0 = 0 +43:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:12/0/physics_layer_0/angular_velocity = 0.0 +44:12/0 = 0 +44:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:12/0/physics_layer_0/angular_velocity = 0.0 +45:12/0 = 0 +45:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:12/0/physics_layer_0/angular_velocity = 0.0 +46:12/0 = 0 +46:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:12/0/physics_layer_0/angular_velocity = 0.0 +47:12/0 = 0 +47:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:12/0/physics_layer_0/angular_velocity = 0.0 +48:12/0 = 0 +48:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:12/0/physics_layer_0/angular_velocity = 0.0 +0:13/0 = 0 +0:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:13/0/physics_layer_0/angular_velocity = 0.0 +1:13/0 = 0 +1:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:13/0/physics_layer_0/angular_velocity = 0.0 +2:13/0 = 0 +2:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:13/0/physics_layer_0/angular_velocity = 0.0 +3:13/0 = 0 +3:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:13/0/physics_layer_0/angular_velocity = 0.0 +4:13/0 = 0 +4:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:13/0/physics_layer_0/angular_velocity = 0.0 +5:13/0 = 0 +5:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:13/0/physics_layer_0/angular_velocity = 0.0 +6:13/0 = 0 +6:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:13/0/physics_layer_0/angular_velocity = 0.0 +7:13/0 = 0 +7:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:13/0/physics_layer_0/angular_velocity = 0.0 +8:13/0 = 0 +8:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:13/0/physics_layer_0/angular_velocity = 0.0 +9:13/0 = 0 +9:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:13/0/physics_layer_0/angular_velocity = 0.0 +10:13/0 = 0 +10:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:13/0/physics_layer_0/angular_velocity = 0.0 +11:13/0 = 0 +11:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:13/0/physics_layer_0/angular_velocity = 0.0 +12:13/0 = 0 +12:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:13/0/physics_layer_0/angular_velocity = 0.0 +13:13/0 = 0 +13:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:13/0/physics_layer_0/angular_velocity = 0.0 +14:13/0 = 0 +14:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:13/0/physics_layer_0/angular_velocity = 0.0 +15:13/0 = 0 +15:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:13/0/physics_layer_0/angular_velocity = 0.0 +16:13/0 = 0 +16:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:13/0/physics_layer_0/angular_velocity = 0.0 +17:13/0 = 0 +17:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:13/0/physics_layer_0/angular_velocity = 0.0 +18:13/0 = 0 +18:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:13/0/physics_layer_0/angular_velocity = 0.0 +19:13/0 = 0 +19:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:13/0/physics_layer_0/angular_velocity = 0.0 +20:13/0 = 0 +20:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:13/0/physics_layer_0/angular_velocity = 0.0 +21:13/0 = 0 +21:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:13/0/physics_layer_0/angular_velocity = 0.0 +22:13/0 = 0 +22:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:13/0/physics_layer_0/angular_velocity = 0.0 +23:13/0 = 0 +23:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:13/0/physics_layer_0/angular_velocity = 0.0 +24:13/0 = 0 +24:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:13/0/physics_layer_0/angular_velocity = 0.0 +25:13/0 = 0 +25:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:13/0/physics_layer_0/angular_velocity = 0.0 +26:13/0 = 0 +26:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:13/0/physics_layer_0/angular_velocity = 0.0 +27:13/0 = 0 +27:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:13/0/physics_layer_0/angular_velocity = 0.0 +28:13/0 = 0 +28:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:13/0/physics_layer_0/angular_velocity = 0.0 +29:13/0 = 0 +29:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:13/0/physics_layer_0/angular_velocity = 0.0 +30:13/0 = 0 +30:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:13/0/physics_layer_0/angular_velocity = 0.0 +31:13/0 = 0 +31:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:13/0/physics_layer_0/angular_velocity = 0.0 +32:13/0 = 0 +32:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:13/0/physics_layer_0/angular_velocity = 0.0 +33:13/0 = 0 +33:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:13/0/physics_layer_0/angular_velocity = 0.0 +34:13/0 = 0 +34:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:13/0/physics_layer_0/angular_velocity = 0.0 +35:13/0 = 0 +35:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:13/0/physics_layer_0/angular_velocity = 0.0 +36:13/0 = 0 +36:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:13/0/physics_layer_0/angular_velocity = 0.0 +37:13/0 = 0 +37:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:13/0/physics_layer_0/angular_velocity = 0.0 +38:13/0 = 0 +38:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:13/0/physics_layer_0/angular_velocity = 0.0 +39:13/0 = 0 +39:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:13/0/physics_layer_0/angular_velocity = 0.0 +40:13/0 = 0 +40:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:13/0/physics_layer_0/angular_velocity = 0.0 +41:13/0 = 0 +41:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:13/0/physics_layer_0/angular_velocity = 0.0 +42:13/0 = 0 +42:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:13/0/physics_layer_0/angular_velocity = 0.0 +43:13/0 = 0 +43:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:13/0/physics_layer_0/angular_velocity = 0.0 +44:13/0 = 0 +44:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:13/0/physics_layer_0/angular_velocity = 0.0 +45:13/0 = 0 +45:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:13/0/physics_layer_0/angular_velocity = 0.0 +46:13/0 = 0 +46:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:13/0/physics_layer_0/angular_velocity = 0.0 +47:13/0 = 0 +47:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:13/0/physics_layer_0/angular_velocity = 0.0 +48:13/0 = 0 +48:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:13/0/physics_layer_0/angular_velocity = 0.0 +0:14/0 = 0 +0:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:14/0/physics_layer_0/angular_velocity = 0.0 +1:14/0 = 0 +1:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:14/0/physics_layer_0/angular_velocity = 0.0 +2:14/0 = 0 +2:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:14/0/physics_layer_0/angular_velocity = 0.0 +3:14/0 = 0 +3:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:14/0/physics_layer_0/angular_velocity = 0.0 +4:14/0 = 0 +4:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:14/0/physics_layer_0/angular_velocity = 0.0 +5:14/0 = 0 +5:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:14/0/physics_layer_0/angular_velocity = 0.0 +6:14/0 = 0 +6:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:14/0/physics_layer_0/angular_velocity = 0.0 +7:14/0 = 0 +7:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:14/0/physics_layer_0/angular_velocity = 0.0 +8:14/0 = 0 +8:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:14/0/physics_layer_0/angular_velocity = 0.0 +9:14/0 = 0 +9:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:14/0/physics_layer_0/angular_velocity = 0.0 +10:14/0 = 0 +10:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:14/0/physics_layer_0/angular_velocity = 0.0 +11:14/0 = 0 +11:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:14/0/physics_layer_0/angular_velocity = 0.0 +12:14/0 = 0 +12:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:14/0/physics_layer_0/angular_velocity = 0.0 +13:14/0 = 0 +13:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:14/0/physics_layer_0/angular_velocity = 0.0 +14:14/0 = 0 +14:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:14/0/physics_layer_0/angular_velocity = 0.0 +15:14/0 = 0 +15:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:14/0/physics_layer_0/angular_velocity = 0.0 +16:14/0 = 0 +16:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:14/0/physics_layer_0/angular_velocity = 0.0 +17:14/0 = 0 +17:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:14/0/physics_layer_0/angular_velocity = 0.0 +18:14/0 = 0 +18:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:14/0/physics_layer_0/angular_velocity = 0.0 +19:14/0 = 0 +19:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:14/0/physics_layer_0/angular_velocity = 0.0 +20:14/0 = 0 +20:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:14/0/physics_layer_0/angular_velocity = 0.0 +21:14/0 = 0 +21:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:14/0/physics_layer_0/angular_velocity = 0.0 +22:14/0 = 0 +22:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:14/0/physics_layer_0/angular_velocity = 0.0 +23:14/0 = 0 +23:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:14/0/physics_layer_0/angular_velocity = 0.0 +24:14/0 = 0 +24:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:14/0/physics_layer_0/angular_velocity = 0.0 +25:14/0 = 0 +25:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:14/0/physics_layer_0/angular_velocity = 0.0 +26:14/0 = 0 +26:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:14/0/physics_layer_0/angular_velocity = 0.0 +27:14/0 = 0 +27:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:14/0/physics_layer_0/angular_velocity = 0.0 +28:14/0 = 0 +28:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:14/0/physics_layer_0/angular_velocity = 0.0 +29:14/0 = 0 +29:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:14/0/physics_layer_0/angular_velocity = 0.0 +30:14/0 = 0 +30:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:14/0/physics_layer_0/angular_velocity = 0.0 +31:14/0 = 0 +31:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:14/0/physics_layer_0/angular_velocity = 0.0 +32:14/0 = 0 +32:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:14/0/physics_layer_0/angular_velocity = 0.0 +33:14/0 = 0 +33:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:14/0/physics_layer_0/angular_velocity = 0.0 +34:14/0 = 0 +34:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:14/0/physics_layer_0/angular_velocity = 0.0 +35:14/0 = 0 +35:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:14/0/physics_layer_0/angular_velocity = 0.0 +36:14/0 = 0 +36:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:14/0/physics_layer_0/angular_velocity = 0.0 +37:14/0 = 0 +37:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:14/0/physics_layer_0/angular_velocity = 0.0 +38:14/0 = 0 +38:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:14/0/physics_layer_0/angular_velocity = 0.0 +39:14/0 = 0 +39:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:14/0/physics_layer_0/angular_velocity = 0.0 +40:14/0 = 0 +40:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:14/0/physics_layer_0/angular_velocity = 0.0 +41:14/0 = 0 +41:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:14/0/physics_layer_0/angular_velocity = 0.0 +42:14/0 = 0 +42:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:14/0/physics_layer_0/angular_velocity = 0.0 +43:14/0 = 0 +43:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:14/0/physics_layer_0/angular_velocity = 0.0 +44:14/0 = 0 +44:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:14/0/physics_layer_0/angular_velocity = 0.0 +45:14/0 = 0 +45:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:14/0/physics_layer_0/angular_velocity = 0.0 +46:14/0 = 0 +46:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:14/0/physics_layer_0/angular_velocity = 0.0 +47:14/0 = 0 +47:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:14/0/physics_layer_0/angular_velocity = 0.0 +48:14/0 = 0 +48:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:14/0/physics_layer_0/angular_velocity = 0.0 +0:15/0 = 0 +0:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:15/0/physics_layer_0/angular_velocity = 0.0 +1:15/0 = 0 +1:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:15/0/physics_layer_0/angular_velocity = 0.0 +2:15/0 = 0 +2:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:15/0/physics_layer_0/angular_velocity = 0.0 +3:15/0 = 0 +3:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:15/0/physics_layer_0/angular_velocity = 0.0 +4:15/0 = 0 +4:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:15/0/physics_layer_0/angular_velocity = 0.0 +5:15/0 = 0 +5:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:15/0/physics_layer_0/angular_velocity = 0.0 +6:15/0 = 0 +6:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:15/0/physics_layer_0/angular_velocity = 0.0 +7:15/0 = 0 +7:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:15/0/physics_layer_0/angular_velocity = 0.0 +8:15/0 = 0 +8:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:15/0/physics_layer_0/angular_velocity = 0.0 +9:15/0 = 0 +9:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:15/0/physics_layer_0/angular_velocity = 0.0 +10:15/0 = 0 +10:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:15/0/physics_layer_0/angular_velocity = 0.0 +11:15/0 = 0 +11:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:15/0/physics_layer_0/angular_velocity = 0.0 +12:15/0 = 0 +12:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:15/0/physics_layer_0/angular_velocity = 0.0 +13:15/0 = 0 +13:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:15/0/physics_layer_0/angular_velocity = 0.0 +14:15/0 = 0 +14:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:15/0/physics_layer_0/angular_velocity = 0.0 +15:15/0 = 0 +15:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:15/0/physics_layer_0/angular_velocity = 0.0 +16:15/0 = 0 +16:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:15/0/physics_layer_0/angular_velocity = 0.0 +17:15/0 = 0 +17:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:15/0/physics_layer_0/angular_velocity = 0.0 +18:15/0 = 0 +18:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:15/0/physics_layer_0/angular_velocity = 0.0 +19:15/0 = 0 +19:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:15/0/physics_layer_0/angular_velocity = 0.0 +20:15/0 = 0 +20:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:15/0/physics_layer_0/angular_velocity = 0.0 +21:15/0 = 0 +21:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:15/0/physics_layer_0/angular_velocity = 0.0 +22:15/0 = 0 +22:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:15/0/physics_layer_0/angular_velocity = 0.0 +23:15/0 = 0 +23:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:15/0/physics_layer_0/angular_velocity = 0.0 +24:15/0 = 0 +24:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:15/0/physics_layer_0/angular_velocity = 0.0 +25:15/0 = 0 +25:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:15/0/physics_layer_0/angular_velocity = 0.0 +26:15/0 = 0 +26:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:15/0/physics_layer_0/angular_velocity = 0.0 +27:15/0 = 0 +27:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:15/0/physics_layer_0/angular_velocity = 0.0 +28:15/0 = 0 +28:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:15/0/physics_layer_0/angular_velocity = 0.0 +29:15/0 = 0 +29:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:15/0/physics_layer_0/angular_velocity = 0.0 +30:15/0 = 0 +30:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:15/0/physics_layer_0/angular_velocity = 0.0 +31:15/0 = 0 +31:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:15/0/physics_layer_0/angular_velocity = 0.0 +32:15/0 = 0 +32:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:15/0/physics_layer_0/angular_velocity = 0.0 +33:15/0 = 0 +33:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:15/0/physics_layer_0/angular_velocity = 0.0 +34:15/0 = 0 +34:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:15/0/physics_layer_0/angular_velocity = 0.0 +35:15/0 = 0 +35:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:15/0/physics_layer_0/angular_velocity = 0.0 +36:15/0 = 0 +36:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:15/0/physics_layer_0/angular_velocity = 0.0 +37:15/0 = 0 +37:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:15/0/physics_layer_0/angular_velocity = 0.0 +38:15/0 = 0 +38:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:15/0/physics_layer_0/angular_velocity = 0.0 +39:15/0 = 0 +39:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:15/0/physics_layer_0/angular_velocity = 0.0 +40:15/0 = 0 +40:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:15/0/physics_layer_0/angular_velocity = 0.0 +41:15/0 = 0 +41:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:15/0/physics_layer_0/angular_velocity = 0.0 +42:15/0 = 0 +42:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:15/0/physics_layer_0/angular_velocity = 0.0 +43:15/0 = 0 +43:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:15/0/physics_layer_0/angular_velocity = 0.0 +44:15/0 = 0 +44:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:15/0/physics_layer_0/angular_velocity = 0.0 +45:15/0 = 0 +45:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:15/0/physics_layer_0/angular_velocity = 0.0 +46:15/0 = 0 +46:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:15/0/physics_layer_0/angular_velocity = 0.0 +47:15/0 = 0 +47:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:15/0/physics_layer_0/angular_velocity = 0.0 +48:15/0 = 0 +48:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:15/0/physics_layer_0/angular_velocity = 0.0 +0:16/0 = 0 +0:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:16/0/physics_layer_0/angular_velocity = 0.0 +1:16/0 = 0 +1:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:16/0/physics_layer_0/angular_velocity = 0.0 +2:16/0 = 0 +2:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:16/0/physics_layer_0/angular_velocity = 0.0 +3:16/0 = 0 +3:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:16/0/physics_layer_0/angular_velocity = 0.0 +4:16/0 = 0 +4:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:16/0/physics_layer_0/angular_velocity = 0.0 +5:16/0 = 0 +5:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:16/0/physics_layer_0/angular_velocity = 0.0 +6:16/0 = 0 +6:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:16/0/physics_layer_0/angular_velocity = 0.0 +7:16/0 = 0 +7:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:16/0/physics_layer_0/angular_velocity = 0.0 +8:16/0 = 0 +8:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:16/0/physics_layer_0/angular_velocity = 0.0 +9:16/0 = 0 +9:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:16/0/physics_layer_0/angular_velocity = 0.0 +10:16/0 = 0 +10:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:16/0/physics_layer_0/angular_velocity = 0.0 +11:16/0 = 0 +11:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:16/0/physics_layer_0/angular_velocity = 0.0 +12:16/0 = 0 +12:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:16/0/physics_layer_0/angular_velocity = 0.0 +13:16/0 = 0 +13:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:16/0/physics_layer_0/angular_velocity = 0.0 +14:16/0 = 0 +14:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:16/0/physics_layer_0/angular_velocity = 0.0 +15:16/0 = 0 +15:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:16/0/physics_layer_0/angular_velocity = 0.0 +16:16/0 = 0 +16:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:16/0/physics_layer_0/angular_velocity = 0.0 +17:16/0 = 0 +17:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:16/0/physics_layer_0/angular_velocity = 0.0 +18:16/0 = 0 +18:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:16/0/physics_layer_0/angular_velocity = 0.0 +19:16/0 = 0 +19:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:16/0/physics_layer_0/angular_velocity = 0.0 +20:16/0 = 0 +20:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:16/0/physics_layer_0/angular_velocity = 0.0 +21:16/0 = 0 +21:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:16/0/physics_layer_0/angular_velocity = 0.0 +22:16/0 = 0 +22:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:16/0/physics_layer_0/angular_velocity = 0.0 +23:16/0 = 0 +23:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:16/0/physics_layer_0/angular_velocity = 0.0 +24:16/0 = 0 +24:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:16/0/physics_layer_0/angular_velocity = 0.0 +25:16/0 = 0 +25:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:16/0/physics_layer_0/angular_velocity = 0.0 +26:16/0 = 0 +26:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:16/0/physics_layer_0/angular_velocity = 0.0 +27:16/0 = 0 +27:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:16/0/physics_layer_0/angular_velocity = 0.0 +28:16/0 = 0 +28:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:16/0/physics_layer_0/angular_velocity = 0.0 +29:16/0 = 0 +29:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:16/0/physics_layer_0/angular_velocity = 0.0 +30:16/0 = 0 +30:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:16/0/physics_layer_0/angular_velocity = 0.0 +31:16/0 = 0 +31:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:16/0/physics_layer_0/angular_velocity = 0.0 +32:16/0 = 0 +32:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:16/0/physics_layer_0/angular_velocity = 0.0 +33:16/0 = 0 +33:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:16/0/physics_layer_0/angular_velocity = 0.0 +34:16/0 = 0 +34:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:16/0/physics_layer_0/angular_velocity = 0.0 +35:16/0 = 0 +35:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:16/0/physics_layer_0/angular_velocity = 0.0 +36:16/0 = 0 +36:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:16/0/physics_layer_0/angular_velocity = 0.0 +37:16/0 = 0 +37:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:16/0/physics_layer_0/angular_velocity = 0.0 +38:16/0 = 0 +38:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:16/0/physics_layer_0/angular_velocity = 0.0 +39:16/0 = 0 +39:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:16/0/physics_layer_0/angular_velocity = 0.0 +40:16/0 = 0 +40:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:16/0/physics_layer_0/angular_velocity = 0.0 +41:16/0 = 0 +41:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:16/0/physics_layer_0/angular_velocity = 0.0 +42:16/0 = 0 +42:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:16/0/physics_layer_0/angular_velocity = 0.0 +43:16/0 = 0 +43:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:16/0/physics_layer_0/angular_velocity = 0.0 +44:16/0 = 0 +44:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:16/0/physics_layer_0/angular_velocity = 0.0 +45:16/0 = 0 +45:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:16/0/physics_layer_0/angular_velocity = 0.0 +46:16/0 = 0 +46:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:16/0/physics_layer_0/angular_velocity = 0.0 +47:16/0 = 0 +47:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:16/0/physics_layer_0/angular_velocity = 0.0 +48:16/0 = 0 +48:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:16/0/physics_layer_0/angular_velocity = 0.0 +0:17/0 = 0 +0:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:17/0/physics_layer_0/angular_velocity = 0.0 +1:17/0 = 0 +1:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:17/0/physics_layer_0/angular_velocity = 0.0 +2:17/0 = 0 +2:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:17/0/physics_layer_0/angular_velocity = 0.0 +3:17/0 = 0 +3:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:17/0/physics_layer_0/angular_velocity = 0.0 +4:17/0 = 0 +4:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:17/0/physics_layer_0/angular_velocity = 0.0 +5:17/0 = 0 +5:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:17/0/physics_layer_0/angular_velocity = 0.0 +6:17/0 = 0 +6:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:17/0/physics_layer_0/angular_velocity = 0.0 +7:17/0 = 0 +7:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:17/0/physics_layer_0/angular_velocity = 0.0 +8:17/0 = 0 +8:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:17/0/physics_layer_0/angular_velocity = 0.0 +9:17/0 = 0 +9:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:17/0/physics_layer_0/angular_velocity = 0.0 +10:17/0 = 0 +10:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:17/0/physics_layer_0/angular_velocity = 0.0 +11:17/0 = 0 +11:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:17/0/physics_layer_0/angular_velocity = 0.0 +12:17/0 = 0 +12:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:17/0/physics_layer_0/angular_velocity = 0.0 +13:17/0 = 0 +13:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:17/0/physics_layer_0/angular_velocity = 0.0 +14:17/0 = 0 +14:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:17/0/physics_layer_0/angular_velocity = 0.0 +15:17/0 = 0 +15:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:17/0/physics_layer_0/angular_velocity = 0.0 +16:17/0 = 0 +16:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:17/0/physics_layer_0/angular_velocity = 0.0 +17:17/0 = 0 +17:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:17/0/physics_layer_0/angular_velocity = 0.0 +18:17/0 = 0 +18:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:17/0/physics_layer_0/angular_velocity = 0.0 +19:17/0 = 0 +19:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:17/0/physics_layer_0/angular_velocity = 0.0 +20:17/0 = 0 +20:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:17/0/physics_layer_0/angular_velocity = 0.0 +21:17/0 = 0 +21:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:17/0/physics_layer_0/angular_velocity = 0.0 +22:17/0 = 0 +22:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:17/0/physics_layer_0/angular_velocity = 0.0 +23:17/0 = 0 +23:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:17/0/physics_layer_0/angular_velocity = 0.0 +24:17/0 = 0 +24:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:17/0/physics_layer_0/angular_velocity = 0.0 +25:17/0 = 0 +25:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:17/0/physics_layer_0/angular_velocity = 0.0 +26:17/0 = 0 +26:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:17/0/physics_layer_0/angular_velocity = 0.0 +27:17/0 = 0 +27:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:17/0/physics_layer_0/angular_velocity = 0.0 +28:17/0 = 0 +28:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:17/0/physics_layer_0/angular_velocity = 0.0 +29:17/0 = 0 +29:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:17/0/physics_layer_0/angular_velocity = 0.0 +30:17/0 = 0 +30:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:17/0/physics_layer_0/angular_velocity = 0.0 +31:17/0 = 0 +31:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:17/0/physics_layer_0/angular_velocity = 0.0 +32:17/0 = 0 +32:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:17/0/physics_layer_0/angular_velocity = 0.0 +33:17/0 = 0 +33:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:17/0/physics_layer_0/angular_velocity = 0.0 +34:17/0 = 0 +34:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:17/0/physics_layer_0/angular_velocity = 0.0 +35:17/0 = 0 +35:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:17/0/physics_layer_0/angular_velocity = 0.0 +36:17/0 = 0 +36:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:17/0/physics_layer_0/angular_velocity = 0.0 +37:17/0 = 0 +37:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:17/0/physics_layer_0/angular_velocity = 0.0 +38:17/0 = 0 +38:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:17/0/physics_layer_0/angular_velocity = 0.0 +39:17/0 = 0 +39:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:17/0/physics_layer_0/angular_velocity = 0.0 +40:17/0 = 0 +40:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:17/0/physics_layer_0/angular_velocity = 0.0 +41:17/0 = 0 +41:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:17/0/physics_layer_0/angular_velocity = 0.0 +42:17/0 = 0 +42:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:17/0/physics_layer_0/angular_velocity = 0.0 +43:17/0 = 0 +43:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:17/0/physics_layer_0/angular_velocity = 0.0 +44:17/0 = 0 +44:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:17/0/physics_layer_0/angular_velocity = 0.0 +45:17/0 = 0 +45:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:17/0/physics_layer_0/angular_velocity = 0.0 +46:17/0 = 0 +46:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:17/0/physics_layer_0/angular_velocity = 0.0 +47:17/0 = 0 +47:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:17/0/physics_layer_0/angular_velocity = 0.0 +48:17/0 = 0 +48:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:17/0/physics_layer_0/angular_velocity = 0.0 +0:18/0 = 0 +0:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:18/0/physics_layer_0/angular_velocity = 0.0 +1:18/0 = 0 +1:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:18/0/physics_layer_0/angular_velocity = 0.0 +2:18/0 = 0 +2:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:18/0/physics_layer_0/angular_velocity = 0.0 +3:18/0 = 0 +3:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:18/0/physics_layer_0/angular_velocity = 0.0 +4:18/0 = 0 +4:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:18/0/physics_layer_0/angular_velocity = 0.0 +5:18/0 = 0 +5:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:18/0/physics_layer_0/angular_velocity = 0.0 +6:18/0 = 0 +6:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:18/0/physics_layer_0/angular_velocity = 0.0 +7:18/0 = 0 +7:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:18/0/physics_layer_0/angular_velocity = 0.0 +8:18/0 = 0 +8:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:18/0/physics_layer_0/angular_velocity = 0.0 +9:18/0 = 0 +9:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:18/0/physics_layer_0/angular_velocity = 0.0 +10:18/0 = 0 +10:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:18/0/physics_layer_0/angular_velocity = 0.0 +11:18/0 = 0 +11:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:18/0/physics_layer_0/angular_velocity = 0.0 +12:18/0 = 0 +12:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:18/0/physics_layer_0/angular_velocity = 0.0 +13:18/0 = 0 +13:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:18/0/physics_layer_0/angular_velocity = 0.0 +14:18/0 = 0 +14:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:18/0/physics_layer_0/angular_velocity = 0.0 +15:18/0 = 0 +15:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:18/0/physics_layer_0/angular_velocity = 0.0 +16:18/0 = 0 +16:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:18/0/physics_layer_0/angular_velocity = 0.0 +17:18/0 = 0 +17:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:18/0/physics_layer_0/angular_velocity = 0.0 +18:18/0 = 0 +18:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:18/0/physics_layer_0/angular_velocity = 0.0 +19:18/0 = 0 +19:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:18/0/physics_layer_0/angular_velocity = 0.0 +20:18/0 = 0 +20:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:18/0/physics_layer_0/angular_velocity = 0.0 +21:18/0 = 0 +21:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:18/0/physics_layer_0/angular_velocity = 0.0 +22:18/0 = 0 +22:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:18/0/physics_layer_0/angular_velocity = 0.0 +23:18/0 = 0 +23:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:18/0/physics_layer_0/angular_velocity = 0.0 +24:18/0 = 0 +24:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:18/0/physics_layer_0/angular_velocity = 0.0 +25:18/0 = 0 +25:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:18/0/physics_layer_0/angular_velocity = 0.0 +26:18/0 = 0 +26:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:18/0/physics_layer_0/angular_velocity = 0.0 +27:18/0 = 0 +27:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:18/0/physics_layer_0/angular_velocity = 0.0 +28:18/0 = 0 +28:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:18/0/physics_layer_0/angular_velocity = 0.0 +29:18/0 = 0 +29:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:18/0/physics_layer_0/angular_velocity = 0.0 +30:18/0 = 0 +30:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:18/0/physics_layer_0/angular_velocity = 0.0 +31:18/0 = 0 +31:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:18/0/physics_layer_0/angular_velocity = 0.0 +32:18/0 = 0 +32:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:18/0/physics_layer_0/angular_velocity = 0.0 +33:18/0 = 0 +33:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:18/0/physics_layer_0/angular_velocity = 0.0 +34:18/0 = 0 +34:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:18/0/physics_layer_0/angular_velocity = 0.0 +35:18/0 = 0 +35:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:18/0/physics_layer_0/angular_velocity = 0.0 +36:18/0 = 0 +36:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:18/0/physics_layer_0/angular_velocity = 0.0 +37:18/0 = 0 +37:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:18/0/physics_layer_0/angular_velocity = 0.0 +38:18/0 = 0 +38:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:18/0/physics_layer_0/angular_velocity = 0.0 +39:18/0 = 0 +39:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:18/0/physics_layer_0/angular_velocity = 0.0 +40:18/0 = 0 +40:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:18/0/physics_layer_0/angular_velocity = 0.0 +41:18/0 = 0 +41:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:18/0/physics_layer_0/angular_velocity = 0.0 +42:18/0 = 0 +42:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:18/0/physics_layer_0/angular_velocity = 0.0 +43:18/0 = 0 +43:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:18/0/physics_layer_0/angular_velocity = 0.0 +44:18/0 = 0 +44:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:18/0/physics_layer_0/angular_velocity = 0.0 +45:18/0 = 0 +45:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:18/0/physics_layer_0/angular_velocity = 0.0 +46:18/0 = 0 +46:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:18/0/physics_layer_0/angular_velocity = 0.0 +47:18/0 = 0 +47:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:18/0/physics_layer_0/angular_velocity = 0.0 +48:18/0 = 0 +48:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:18/0/physics_layer_0/angular_velocity = 0.0 +0:19/0 = 0 +0:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:19/0/physics_layer_0/angular_velocity = 0.0 +1:19/0 = 0 +1:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:19/0/physics_layer_0/angular_velocity = 0.0 +2:19/0 = 0 +2:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:19/0/physics_layer_0/angular_velocity = 0.0 +3:19/0 = 0 +3:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:19/0/physics_layer_0/angular_velocity = 0.0 +4:19/0 = 0 +4:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:19/0/physics_layer_0/angular_velocity = 0.0 +5:19/0 = 0 +5:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:19/0/physics_layer_0/angular_velocity = 0.0 +6:19/0 = 0 +6:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:19/0/physics_layer_0/angular_velocity = 0.0 +7:19/0 = 0 +7:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:19/0/physics_layer_0/angular_velocity = 0.0 +8:19/0 = 0 +8:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:19/0/physics_layer_0/angular_velocity = 0.0 +9:19/0 = 0 +9:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:19/0/physics_layer_0/angular_velocity = 0.0 +10:19/0 = 0 +10:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:19/0/physics_layer_0/angular_velocity = 0.0 +11:19/0 = 0 +11:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:19/0/physics_layer_0/angular_velocity = 0.0 +12:19/0 = 0 +12:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:19/0/physics_layer_0/angular_velocity = 0.0 +13:19/0 = 0 +13:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:19/0/physics_layer_0/angular_velocity = 0.0 +14:19/0 = 0 +14:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:19/0/physics_layer_0/angular_velocity = 0.0 +15:19/0 = 0 +15:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:19/0/physics_layer_0/angular_velocity = 0.0 +16:19/0 = 0 +16:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:19/0/physics_layer_0/angular_velocity = 0.0 +17:19/0 = 0 +17:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:19/0/physics_layer_0/angular_velocity = 0.0 +18:19/0 = 0 +18:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:19/0/physics_layer_0/angular_velocity = 0.0 +19:19/0 = 0 +19:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:19/0/physics_layer_0/angular_velocity = 0.0 +20:19/0 = 0 +20:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:19/0/physics_layer_0/angular_velocity = 0.0 +21:19/0 = 0 +21:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:19/0/physics_layer_0/angular_velocity = 0.0 +22:19/0 = 0 +22:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:19/0/physics_layer_0/angular_velocity = 0.0 +23:19/0 = 0 +23:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:19/0/physics_layer_0/angular_velocity = 0.0 +24:19/0 = 0 +24:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:19/0/physics_layer_0/angular_velocity = 0.0 +25:19/0 = 0 +25:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:19/0/physics_layer_0/angular_velocity = 0.0 +26:19/0 = 0 +26:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:19/0/physics_layer_0/angular_velocity = 0.0 +27:19/0 = 0 +27:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:19/0/physics_layer_0/angular_velocity = 0.0 +28:19/0 = 0 +28:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:19/0/physics_layer_0/angular_velocity = 0.0 +29:19/0 = 0 +29:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:19/0/physics_layer_0/angular_velocity = 0.0 +30:19/0 = 0 +30:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:19/0/physics_layer_0/angular_velocity = 0.0 +31:19/0 = 0 +31:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:19/0/physics_layer_0/angular_velocity = 0.0 +32:19/0 = 0 +32:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:19/0/physics_layer_0/angular_velocity = 0.0 +33:19/0 = 0 +33:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:19/0/physics_layer_0/angular_velocity = 0.0 +34:19/0 = 0 +34:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:19/0/physics_layer_0/angular_velocity = 0.0 +35:19/0 = 0 +35:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:19/0/physics_layer_0/angular_velocity = 0.0 +36:19/0 = 0 +36:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:19/0/physics_layer_0/angular_velocity = 0.0 +37:19/0 = 0 +37:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:19/0/physics_layer_0/angular_velocity = 0.0 +38:19/0 = 0 +38:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:19/0/physics_layer_0/angular_velocity = 0.0 +39:19/0 = 0 +39:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:19/0/physics_layer_0/angular_velocity = 0.0 +40:19/0 = 0 +40:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:19/0/physics_layer_0/angular_velocity = 0.0 +41:19/0 = 0 +41:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:19/0/physics_layer_0/angular_velocity = 0.0 +42:19/0 = 0 +42:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:19/0/physics_layer_0/angular_velocity = 0.0 +43:19/0 = 0 +43:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:19/0/physics_layer_0/angular_velocity = 0.0 +44:19/0 = 0 +44:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:19/0/physics_layer_0/angular_velocity = 0.0 +45:19/0 = 0 +45:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:19/0/physics_layer_0/angular_velocity = 0.0 +46:19/0 = 0 +46:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:19/0/physics_layer_0/angular_velocity = 0.0 +47:19/0 = 0 +47:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:19/0/physics_layer_0/angular_velocity = 0.0 +48:19/0 = 0 +48:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:19/0/physics_layer_0/angular_velocity = 0.0 +0:20/0 = 0 +0:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:20/0/physics_layer_0/angular_velocity = 0.0 +1:20/0 = 0 +1:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:20/0/physics_layer_0/angular_velocity = 0.0 +2:20/0 = 0 +2:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:20/0/physics_layer_0/angular_velocity = 0.0 +3:20/0 = 0 +3:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:20/0/physics_layer_0/angular_velocity = 0.0 +4:20/0 = 0 +4:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:20/0/physics_layer_0/angular_velocity = 0.0 +5:20/0 = 0 +5:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:20/0/physics_layer_0/angular_velocity = 0.0 +6:20/0 = 0 +6:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:20/0/physics_layer_0/angular_velocity = 0.0 +7:20/0 = 0 +7:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:20/0/physics_layer_0/angular_velocity = 0.0 +8:20/0 = 0 +8:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:20/0/physics_layer_0/angular_velocity = 0.0 +9:20/0 = 0 +9:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:20/0/physics_layer_0/angular_velocity = 0.0 +10:20/0 = 0 +10:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:20/0/physics_layer_0/angular_velocity = 0.0 +11:20/0 = 0 +11:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:20/0/physics_layer_0/angular_velocity = 0.0 +12:20/0 = 0 +12:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:20/0/physics_layer_0/angular_velocity = 0.0 +13:20/0 = 0 +13:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:20/0/physics_layer_0/angular_velocity = 0.0 +14:20/0 = 0 +14:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:20/0/physics_layer_0/angular_velocity = 0.0 +15:20/0 = 0 +15:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:20/0/physics_layer_0/angular_velocity = 0.0 +16:20/0 = 0 +16:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:20/0/physics_layer_0/angular_velocity = 0.0 +17:20/0 = 0 +17:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:20/0/physics_layer_0/angular_velocity = 0.0 +18:20/0 = 0 +18:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:20/0/physics_layer_0/angular_velocity = 0.0 +19:20/0 = 0 +19:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:20/0/physics_layer_0/angular_velocity = 0.0 +20:20/0 = 0 +20:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:20/0/physics_layer_0/angular_velocity = 0.0 +21:20/0 = 0 +21:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:20/0/physics_layer_0/angular_velocity = 0.0 +22:20/0 = 0 +22:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:20/0/physics_layer_0/angular_velocity = 0.0 +23:20/0 = 0 +23:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:20/0/physics_layer_0/angular_velocity = 0.0 +24:20/0 = 0 +24:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:20/0/physics_layer_0/angular_velocity = 0.0 +25:20/0 = 0 +25:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:20/0/physics_layer_0/angular_velocity = 0.0 +26:20/0 = 0 +26:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:20/0/physics_layer_0/angular_velocity = 0.0 +27:20/0 = 0 +27:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:20/0/physics_layer_0/angular_velocity = 0.0 +28:20/0 = 0 +28:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:20/0/physics_layer_0/angular_velocity = 0.0 +29:20/0 = 0 +29:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:20/0/physics_layer_0/angular_velocity = 0.0 +30:20/0 = 0 +30:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:20/0/physics_layer_0/angular_velocity = 0.0 +31:20/0 = 0 +31:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:20/0/physics_layer_0/angular_velocity = 0.0 +32:20/0 = 0 +32:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:20/0/physics_layer_0/angular_velocity = 0.0 +33:20/0 = 0 +33:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:20/0/physics_layer_0/angular_velocity = 0.0 +34:20/0 = 0 +34:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:20/0/physics_layer_0/angular_velocity = 0.0 +35:20/0 = 0 +35:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:20/0/physics_layer_0/angular_velocity = 0.0 +36:20/0 = 0 +36:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:20/0/physics_layer_0/angular_velocity = 0.0 +37:20/0 = 0 +37:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:20/0/physics_layer_0/angular_velocity = 0.0 +38:20/0 = 0 +38:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:20/0/physics_layer_0/angular_velocity = 0.0 +39:20/0 = 0 +39:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:20/0/physics_layer_0/angular_velocity = 0.0 +40:20/0 = 0 +40:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:20/0/physics_layer_0/angular_velocity = 0.0 +41:20/0 = 0 +41:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:20/0/physics_layer_0/angular_velocity = 0.0 +42:20/0 = 0 +42:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:20/0/physics_layer_0/angular_velocity = 0.0 +43:20/0 = 0 +43:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:20/0/physics_layer_0/angular_velocity = 0.0 +44:20/0 = 0 +44:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:20/0/physics_layer_0/angular_velocity = 0.0 +45:20/0 = 0 +45:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:20/0/physics_layer_0/angular_velocity = 0.0 +46:20/0 = 0 +46:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:20/0/physics_layer_0/angular_velocity = 0.0 +47:20/0 = 0 +47:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:20/0/physics_layer_0/angular_velocity = 0.0 +48:20/0 = 0 +48:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:20/0/physics_layer_0/angular_velocity = 0.0 +0:21/0 = 0 +0:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:21/0/physics_layer_0/angular_velocity = 0.0 +1:21/0 = 0 +1:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:21/0/physics_layer_0/angular_velocity = 0.0 +2:21/0 = 0 +2:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:21/0/physics_layer_0/angular_velocity = 0.0 +3:21/0 = 0 +3:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:21/0/physics_layer_0/angular_velocity = 0.0 +4:21/0 = 0 +4:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:21/0/physics_layer_0/angular_velocity = 0.0 +5:21/0 = 0 +5:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:21/0/physics_layer_0/angular_velocity = 0.0 +6:21/0 = 0 +6:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:21/0/physics_layer_0/angular_velocity = 0.0 +7:21/0 = 0 +7:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:21/0/physics_layer_0/angular_velocity = 0.0 +8:21/0 = 0 +8:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:21/0/physics_layer_0/angular_velocity = 0.0 +9:21/0 = 0 +9:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:21/0/physics_layer_0/angular_velocity = 0.0 +10:21/0 = 0 +10:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:21/0/physics_layer_0/angular_velocity = 0.0 +11:21/0 = 0 +11:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:21/0/physics_layer_0/angular_velocity = 0.0 +12:21/0 = 0 +12:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:21/0/physics_layer_0/angular_velocity = 0.0 +13:21/0 = 0 +13:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:21/0/physics_layer_0/angular_velocity = 0.0 +14:21/0 = 0 +14:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:21/0/physics_layer_0/angular_velocity = 0.0 +15:21/0 = 0 +15:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:21/0/physics_layer_0/angular_velocity = 0.0 +16:21/0 = 0 +16:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:21/0/physics_layer_0/angular_velocity = 0.0 +17:21/0 = 0 +17:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:21/0/physics_layer_0/angular_velocity = 0.0 +18:21/0 = 0 +18:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:21/0/physics_layer_0/angular_velocity = 0.0 +19:21/0 = 0 +19:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:21/0/physics_layer_0/angular_velocity = 0.0 +20:21/0 = 0 +20:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:21/0/physics_layer_0/angular_velocity = 0.0 +21:21/0 = 0 +21:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:21/0/physics_layer_0/angular_velocity = 0.0 +22:21/0 = 0 +22:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:21/0/physics_layer_0/angular_velocity = 0.0 +23:21/0 = 0 +23:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:21/0/physics_layer_0/angular_velocity = 0.0 +24:21/0 = 0 +24:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:21/0/physics_layer_0/angular_velocity = 0.0 +25:21/0 = 0 +25:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:21/0/physics_layer_0/angular_velocity = 0.0 +26:21/0 = 0 +26:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:21/0/physics_layer_0/angular_velocity = 0.0 +27:21/0 = 0 +27:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:21/0/physics_layer_0/angular_velocity = 0.0 +28:21/0 = 0 +28:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:21/0/physics_layer_0/angular_velocity = 0.0 +29:21/0 = 0 +29:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:21/0/physics_layer_0/angular_velocity = 0.0 +30:21/0 = 0 +30:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:21/0/physics_layer_0/angular_velocity = 0.0 +31:21/0 = 0 +31:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:21/0/physics_layer_0/angular_velocity = 0.0 +32:21/0 = 0 +32:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:21/0/physics_layer_0/angular_velocity = 0.0 +33:21/0 = 0 +33:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:21/0/physics_layer_0/angular_velocity = 0.0 +34:21/0 = 0 +34:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:21/0/physics_layer_0/angular_velocity = 0.0 +35:21/0 = 0 +35:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:21/0/physics_layer_0/angular_velocity = 0.0 +36:21/0 = 0 +36:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:21/0/physics_layer_0/angular_velocity = 0.0 +37:21/0 = 0 +37:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:21/0/physics_layer_0/angular_velocity = 0.0 +38:21/0 = 0 +38:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:21/0/physics_layer_0/angular_velocity = 0.0 +39:21/0 = 0 +39:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:21/0/physics_layer_0/angular_velocity = 0.0 +40:21/0 = 0 +40:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:21/0/physics_layer_0/angular_velocity = 0.0 +41:21/0 = 0 +41:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:21/0/physics_layer_0/angular_velocity = 0.0 +42:21/0 = 0 +42:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:21/0/physics_layer_0/angular_velocity = 0.0 +43:21/0 = 0 +43:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:21/0/physics_layer_0/angular_velocity = 0.0 +44:21/0 = 0 +44:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:21/0/physics_layer_0/angular_velocity = 0.0 +45:21/0 = 0 +45:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:21/0/physics_layer_0/angular_velocity = 0.0 +46:21/0 = 0 +46:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:21/0/physics_layer_0/angular_velocity = 0.0 +47:21/0 = 0 +47:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:21/0/physics_layer_0/angular_velocity = 0.0 +48:21/0 = 0 +48:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:21/0/physics_layer_0/angular_velocity = 0.0 +18:0/0 = 0 +18:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:0/0/physics_layer_0/angular_velocity = 0.0 +18:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) + +[sub_resource type="TileSetScenesCollectionSource" id="TileSetScenesCollectionSource_mi6dp"] +scenes/3/scene = ExtResource("3_uqirg") +scenes/4/scene = ExtResource("2_poklm") + +[resource] +physics_layer_0/collision_layer = 1 +sources/1 = SubResource("TileSetAtlasSource_ari5a") +sources/3 = SubResource("TileSetScenesCollectionSource_mi6dp") diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index dc4fbc6..764c1ea 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -16,7 +16,8 @@ func _ready() -> void: func _on_inspection() -> void: if !opened: - ui.render_text(['I warned you about jayden making ui!!!','now it is in an array','songboots would be nice']) + opened = true + ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) $Sprite2D.frame = 1 diff --git a/src/scene-tiles/stairs/stairs.gd b/src/scene-tiles/stairs/stairs.gd new file mode 100644 index 0000000..c0ff3de --- /dev/null +++ b/src/scene-tiles/stairs/stairs.gd @@ -0,0 +1,8 @@ +extends Area2D + + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + add_to_group('stairs') + pass # Replace with function body. + diff --git a/src/scene-tiles/stairs/stairs.tscn b/src/scene-tiles/stairs/stairs.tscn new file mode 100644 index 0000000..64e00e9 --- /dev/null +++ b/src/scene-tiles/stairs/stairs.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=4 format=3 uid="uid://cmdlpc0uddsm2"] + +[ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_cirol"] +[ext_resource type="Script" path="res://src/scene-tiles/stairs/stairs.gd" id="1_ww3tu"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_8vrfj"] +size = Vector2(16, 16) + +[node name="stairs" type="Area2D"] +script = ExtResource("1_ww3tu") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("RectangleShape2D_8vrfj") + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_cirol") +region_enabled = true +region_rect = Rect2(48, 96, 16, 16) From dea2c6263a1b2ee420c71c7d281cabd1788307a5 Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Thu, 21 Mar 2024 10:55:21 -0400 Subject: [PATCH 11/86] manually added Tigrans contributions --- src/boots/boo1690.tmp | 6 ++++++ src/boots/boots.gd | 46 +++++++++++++++++++++++++++++++++++++++++++ src/boots/boots.tscn | 6 ++++++ src/maps/map.gd | 3 ++- src/player/player.gd | 31 ++++++++++++++++++++++------- 5 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 src/boots/boo1690.tmp create mode 100644 src/boots/boots.gd create mode 100644 src/boots/boots.tscn diff --git a/src/boots/boo1690.tmp b/src/boots/boo1690.tmp new file mode 100644 index 0000000..f9fcf8b --- /dev/null +++ b/src/boots/boo1690.tmp @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://dtgyaic6xsu0h"] + +[ext_resource type="Script" path="res://src/boots/boots.gd" id="1_1p87s"] + +[node name="Boots" type="Node2D"] +script = ExtResource("1_1p87s") diff --git a/src/boots/boots.gd b/src/boots/boots.gd new file mode 100644 index 0000000..18cf409 --- /dev/null +++ b/src/boots/boots.gd @@ -0,0 +1,46 @@ +extends Node2D + + +var winning_move_sequence: Array[String] = ["down","down","down","down","down"] +var past_5_moves: Array[String] = ["","","","",""] + +# Called when the node enters the scene tree for the first time. + +func _ready() -> void: + print("BOOTS ON!!!") + connect_to_player() + +func connect_to_player() -> void: + var parent_player_node = get_node("../") + # Yeah!! You can get stuff 2 parents up the tree get_node("../../") + if parent_player_node != self: + parent_player_node.made_successful_move.connect(new_move_made) + pass + +func new_move_made(dir: Vector2) -> void: + match dir: + Vector2(0,1): + note_new_move("down") + pass + Vector2(0,-1): + note_new_move("up") + pass + Vector2(1,0): + note_new_move("right") + pass + Vector2(-1,0): + note_new_move("left") + pass + has_player_won() + pass + +func note_new_move(what_direction_string: String) -> void: + past_5_moves.pop_front() + past_5_moves.append(what_direction_string) + print(past_5_moves) + pass + +func has_player_won() -> void: + if past_5_moves == winning_move_sequence: + print("yayay!! You won!") + pass diff --git a/src/boots/boots.tscn b/src/boots/boots.tscn new file mode 100644 index 0000000..f9fcf8b --- /dev/null +++ b/src/boots/boots.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://dtgyaic6xsu0h"] + +[ext_resource type="Script" path="res://src/boots/boots.gd" id="1_1p87s"] + +[node name="Boots" type="Node2D"] +script = ExtResource("1_1p87s") diff --git a/src/maps/map.gd b/src/maps/map.gd index fe88449..ad31bcd 100644 --- a/src/maps/map.gd +++ b/src/maps/map.gd @@ -1,9 +1,10 @@ class_name Map extends Node2D - +@onready var tilemap:TileMap = $TileMap # Called when the node enters the scene tree for the first time. func _ready() -> void: + tilemap.add_to_group('wall') pass # Replace with function body. diff --git a/src/player/player.gd b/src/player/player.gd index a6bfd75..ad004fa 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -1,13 +1,17 @@ class_name Player extends Area2D +@onready var boots_packed_scene: PackedScene = preload("res://src/boots/boots.tscn") @onready var raycast := $RayCast2D signal walked_into_stairs +signal made_successful_move(successful_input_dir) const TILE_SIZE := 16 var is_actionable:= true +var has_boots := false + func _init() -> void: add_to_group("player") @@ -48,14 +52,20 @@ func _move(_input_dir:Vector2) -> void: raycast.force_raycast_update() var next_tile: Object = raycast.get_collider() - if next_tile != null: - print(next_tile) - - if next_tile == null: + #if next_tile != null: + #print(next_tile) + # if it's a tile you can interact with you can't walk on it + # maybe we could use class names or something that dosen't require making new labels for everything (not an issue rn) + if next_tile == null or !next_tile.is_in_group('interact'): position += _input_dir * TILE_SIZE - elif next_tile.is_in_group('stairs'): - walked_into_stairs.emit() + made_successful_move.emit(_input_dir) + check_next_tile(next_tile) +func check_next_tile(tile: Object) -> void: + if tile == null: + return + if tile.is_in_group('stairs'): + walked_into_stairs.emit() func _inspect() -> void: raycast.force_raycast_update() @@ -65,7 +75,14 @@ func _inspect() -> void: return if inspect_tile.is_in_group('chest'): inspect_tile._on_inspection() - pass + #very very very bad fix asap + # pass in player into inspection function or something + if !has_boots: + print('boots') + var new_obtained_boots = boots_packed_scene.instantiate() + self.add_child(new_obtained_boots) + has_boots = true + pass pass From 98ad40947de885b171c011d62e583c3aea2e04d8 Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Sat, 23 Mar 2024 18:12:21 -0400 Subject: [PATCH 12/86] cleaned up codebase a bit --- project.godot | 2 +- src/boots/boots.gd | 33 +++++++++++++---------------- src/main/ui.gd | 5 ++--- src/maps/map.gd | 5 ++--- src/player/player.gd | 36 ++++++++++---------------------- src/resources/map_tileset.tres | 1 + src/scene-tiles/chest/chest.gd | 10 ++++++++- src/scene-tiles/stairs/stairs.gd | 1 + 8 files changed, 41 insertions(+), 52 deletions(-) diff --git a/project.godot b/project.godot index 8c5872d..b834fbd 100644 --- a/project.godot +++ b/project.godot @@ -26,7 +26,7 @@ window/stretch/scale_mode="integer" [input] -inspect={ +interact={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) ] diff --git a/src/boots/boots.gd b/src/boots/boots.gd index 18cf409..2ffbbe8 100644 --- a/src/boots/boots.gd +++ b/src/boots/boots.gd @@ -1,8 +1,8 @@ extends Node2D -var winning_move_sequence: Array[String] = ["down","down","down","down","down"] -var past_5_moves: Array[String] = ["","","","",""] +var move_code: Array[String] = ["down","down","down","down","down"] +var recent_moves: Array[String] = ["","","","",""] # Called when the node enters the scene tree for the first time. @@ -11,36 +11,31 @@ func _ready() -> void: connect_to_player() func connect_to_player() -> void: - var parent_player_node = get_node("../") + var player := get_node("../") # Yeah!! You can get stuff 2 parents up the tree get_node("../../") - if parent_player_node != self: - parent_player_node.made_successful_move.connect(new_move_made) - pass + if player != self: + player.moved.connect(player_moved) -func new_move_made(dir: Vector2) -> void: +func player_moved(dir: Vector2) -> void: match dir: Vector2(0,1): - note_new_move("down") + push_move("down") pass Vector2(0,-1): - note_new_move("up") + push_move("up") pass Vector2(1,0): - note_new_move("right") + push_move("right") pass Vector2(-1,0): - note_new_move("left") + push_move("left") pass has_player_won() - pass -func note_new_move(what_direction_string: String) -> void: - past_5_moves.pop_front() - past_5_moves.append(what_direction_string) - print(past_5_moves) - pass +func push_move(what_direction_string: String) -> void: + recent_moves.pop_front() + recent_moves.append(what_direction_string) func has_player_won() -> void: - if past_5_moves == winning_move_sequence: + if recent_moves == move_code: print("yayay!! You won!") - pass diff --git a/src/main/ui.gd b/src/main/ui.gd index bdde533..a7c02d2 100644 --- a/src/main/ui.gd +++ b/src/main/ui.gd @@ -14,12 +14,11 @@ func render_text(new_text_arr) -> void: bootIcon.visible = true textbox.visible = true var textLabel = $Textbox/Text - #i = 0 - #while i < new_text_arr.length(): + for line in new_text_arr: textLabel.text = line await text_advanced - #await text_advanced + textbox.visible = false text_removed.emit() diff --git a/src/maps/map.gd b/src/maps/map.gd index ad31bcd..d392bb2 100644 --- a/src/maps/map.gd +++ b/src/maps/map.gd @@ -1,13 +1,12 @@ class_name Map extends Node2D +# we need to add a collision shape to the tilemap for the player raycast to be able to detect it, otherwise it'll be considered null. + @onready var tilemap:TileMap = $TileMap -# Called when the node enters the scene tree for the first time. func _ready() -> void: tilemap.add_to_group('wall') - pass # Replace with function body. -# Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass diff --git a/src/player/player.gd b/src/player/player.gd index ad004fa..9a5a421 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -5,7 +5,7 @@ extends Area2D @onready var raycast := $RayCast2D signal walked_into_stairs -signal made_successful_move(successful_input_dir) +signal moved(dir) const TILE_SIZE := 16 var is_actionable:= true @@ -42,8 +42,8 @@ func _input(event: InputEvent) -> void: if _input_dir != Vector2.ZERO: _move(_input_dir) return - if event.is_action_pressed('inspect'): - _inspect() + if event.is_action_pressed('interact'): + _interact() func _move(_input_dir:Vector2) -> void: @@ -52,13 +52,9 @@ func _move(_input_dir:Vector2) -> void: raycast.force_raycast_update() var next_tile: Object = raycast.get_collider() - #if next_tile != null: - #print(next_tile) - # if it's a tile you can interact with you can't walk on it - # maybe we could use class names or something that dosen't require making new labels for everything (not an issue rn) - if next_tile == null or !next_tile.is_in_group('interact'): + if next_tile == null or next_tile.is_in_group('walkable'): position += _input_dir * TILE_SIZE - made_successful_move.emit(_input_dir) + moved.emit(_input_dir) check_next_tile(next_tile) func check_next_tile(tile: Object) -> void: @@ -67,22 +63,12 @@ func check_next_tile(tile: Object) -> void: if tile.is_in_group('stairs'): walked_into_stairs.emit() -func _inspect() -> void: +func _interact() -> void: raycast.force_raycast_update() - var inspect_tile: Object = raycast.get_collider() - if inspect_tile == null: + var interact_tile: Object = raycast.get_collider() + if interact_tile == null: print('wow nothing!') return - if inspect_tile.is_in_group('chest'): - inspect_tile._on_inspection() - #very very very bad fix asap - # pass in player into inspection function or something - if !has_boots: - print('boots') - var new_obtained_boots = boots_packed_scene.instantiate() - self.add_child(new_obtained_boots) - has_boots = true - pass - - - pass + if interact_tile.is_in_group('interact'): + interact_tile._on_interaction(self) + diff --git a/src/resources/map_tileset.tres b/src/resources/map_tileset.tres index e471ef7..6fa79eb 100644 --- a/src/resources/map_tileset.tres +++ b/src/resources/map_tileset.tres @@ -2668,6 +2668,7 @@ texture = ExtResource("1_q6o4g") 4:18/0 = 0 4:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) 4:18/0/physics_layer_0/angular_velocity = 0.0 +4:18/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) 5:18/0 = 0 5:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) 5:18/0/physics_layer_0/angular_velocity = 0.0 diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 764c1ea..1316976 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -14,9 +14,17 @@ func _init() -> void: func _ready() -> void: pass -func _on_inspection() -> void: +func _on_interaction(player:Player) -> void: if !opened: opened = true + + # we should make a generic chest with the ability to give any item (although we'd need to have some sort of item data strucutre) + if !player.has_boots: + print('boots') + var boots = player.boots_packed_scene.instantiate() + player.add_child(boots) + player.has_boots = true + ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) $Sprite2D.frame = 1 diff --git a/src/scene-tiles/stairs/stairs.gd b/src/scene-tiles/stairs/stairs.gd index c0ff3de..b57aeb8 100644 --- a/src/scene-tiles/stairs/stairs.gd +++ b/src/scene-tiles/stairs/stairs.gd @@ -3,6 +3,7 @@ extends Area2D # Called when the node enters the scene tree for the first time. func _ready() -> void: + add_to_group('walkable') add_to_group('stairs') pass # Replace with function body. From 4926e4d294b43e8af65ddf3f67bbd92c306ca44d Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Sat, 23 Mar 2024 18:22:21 -0400 Subject: [PATCH 13/86] even cleanergit add -A! --- src/boots/boots.gd | 17 ++++++++--------- src/main/main.gd | 2 -- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/boots/boots.gd b/src/boots/boots.gd index 2ffbbe8..fa7a0cc 100644 --- a/src/boots/boots.gd +++ b/src/boots/boots.gd @@ -11,10 +11,8 @@ func _ready() -> void: connect_to_player() func connect_to_player() -> void: - var player := get_node("../") - # Yeah!! You can get stuff 2 parents up the tree get_node("../../") - if player != self: - player.moved.connect(player_moved) + var player := get_parent() + player.moved.connect(player_moved) func player_moved(dir: Vector2) -> void: match dir: @@ -30,12 +28,13 @@ func player_moved(dir: Vector2) -> void: Vector2(-1,0): push_move("left") pass - has_player_won() -func push_move(what_direction_string: String) -> void: + if recent_moves == move_code: + code_entered() + +func push_move(dir_string: String) -> void: recent_moves.pop_front() - recent_moves.append(what_direction_string) + recent_moves.append(dir_string) -func has_player_won() -> void: - if recent_moves == move_code: +func code_entered(): print("yayay!! You won!") diff --git a/src/main/main.gd b/src/main/main.gd index 0fa48e3..c332444 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -36,8 +36,6 @@ func swap_map() -> void: player.position = playerSpawnMarker.position - - func _start_cutscene() -> void: in_cutscene = true player.is_actionable = false From caea77e7582f340c59f469d3f869bae2921ac2f8 Mon Sep 17 00:00:00 2001 From: Haigsov Date: Sat, 23 Mar 2024 18:55:02 -0400 Subject: [PATCH 14/86] Changed maps from dictionary to array --- src/main/main.gd | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/main/main.gd b/src/main/main.gd index c332444..03da977 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -6,41 +6,41 @@ extends Node2D var in_cutscene := false -var maps:Dictionary = {0:preload('res://src/maps/map-1.tscn'),1:preload('res://src/maps/map-2.tscn'),2:preload('res://src/maps/map-3.tscn')} +var maps:Array = [preload('res://src/maps/map-1.tscn'),preload('res://src/maps/map-2.tscn'),preload('res://src/maps/map-3.tscn')] var shuffled_maps:Array = [] var current_map_id func _ready() -> void: - ui.text_rendered.connect(_start_cutscene) - ui.text_removed.connect(_end_cutscene) - player.walked_into_stairs.connect(swap_map) - pass + ui.text_rendered.connect(_start_cutscene) + ui.text_removed.connect(_end_cutscene) + player.walked_into_stairs.connect(swap_map) + pass func swap_map() -> void: - #reshuffle rooms if we've visted them all - if shuffled_maps.size() == 0: - shuffled_maps = Array(range(maps.size())) - shuffled_maps.shuffle() - #pick new room from remaining choices - var next_map_id :int = shuffled_maps.pop_front() - var nextMap:Node2D = maps[next_map_id].instantiate() + #reshuffle rooms if we've visted them all + if shuffled_maps.size() == 0: + shuffled_maps = Array(range(maps.size())) + shuffled_maps.shuffle() + #pick new room from remaining choices + var next_map_id :int = shuffled_maps.pop_front() + var nextMap:Node2D = maps[next_map_id].instantiate() - #load new map - current_map.queue_free() - add_child(nextMap) - current_map = nextMap + #load new map + current_map.queue_free() + add_child(nextMap) + current_map = nextMap - #move the player to the spawn point - var playerSpawnMarker:Marker2D = nextMap.get_node('PlayerSpawn') - player.position = playerSpawnMarker.position + #move the player to the spawn point + var playerSpawnMarker:Marker2D = nextMap.get_node('PlayerSpawn') + player.position = playerSpawnMarker.position func _start_cutscene() -> void: - in_cutscene = true - player.is_actionable = false + in_cutscene = true + player.is_actionable = false func _end_cutscene() -> void: - in_cutscene = false - await get_tree().create_timer(0.01).timeout # 10ms buffer hack to prevent input collision from text advancing and player input, could also solve by checking UI input in player _input event? - player.is_actionable = true + in_cutscene = false + await get_tree().create_timer(0.01).timeout # 10ms buffer hack to prevent input collision from text advancing and player input, could also solve by checking UI input in player _input event? + player.is_actionable = true From a56df159e43ece8d259edefbca7fb6abc473d4ad Mon Sep 17 00:00:00 2001 From: Haigsov Date: Sat, 23 Mar 2024 21:20:53 -0400 Subject: [PATCH 15/86] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4709183..75eb8af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ # Godot 4+ specific ignores .godot/ +.vscode/settings.json From ae719de33d55d44730c9bacebad35b01e1336a23 Mon Sep 17 00:00:00 2001 From: Haigsov Date: Sun, 24 Mar 2024 23:34:24 -0400 Subject: [PATCH 16/86] Added new case for opening chest when wearing boots --- src/scene-tiles/chest/chest.gd | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 1316976..643a03b 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -25,7 +25,14 @@ func _on_interaction(player:Player) -> void: player.add_child(boots) player.has_boots = true - ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) - $Sprite2D.frame = 1 + ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) + $Sprite2D.frame = 1 + + # added a cheeky placeholder if statement for when the player is already wearing boots and opens a new chest + # did it for shits and giggles + elif player.has_boots: + print('boots again?') + + ui.render_text(['The chest contained the same boots.', "The ones you're already wearing.", 'You don\'t need them right now.']) From b8518ca3ebbd7fa602087fcb13ab73dae7404f3e Mon Sep 17 00:00:00 2001 From: Haigsov Date: Sat, 30 Mar 2024 23:36:14 -0400 Subject: [PATCH 17/86] Create The Maze.md --- The Maze.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 The Maze.md diff --git a/The Maze.md b/The Maze.md new file mode 100644 index 0000000..284f149 --- /dev/null +++ b/The Maze.md @@ -0,0 +1,52 @@ +# Main Gameplay loop +Puzzle RPG +interacting with NPCs and using their info to solve puzzles while also fighting enemies using grid movement turn based combat (similar to crypt of the necrodancer) and might have magic spells, might. +# Verbs (mechanics) +Movement before boots +Interacting (z) +Movement after boots: 8 different types of sound 4 of them +move one time the other move a second time +## in the talks +melee combat +### can be scrapped +spells +take off boots +# To Do +## Game +What type of sounds do we want? 8 notes on a scale from a particular sound can be an instrument +How de we translate to the player what the sounds do? Chests tell you? should be done in first room? +How many rooms in total? 6 rooms excluding tutorial room +## Enemies +Cows (Chests hate them cause they moo and smell) +Bees (Chests are scared of them cause they sting) +Chests won't talk to you unless you defeat them +## Rooms +Every room has a chest no matter what +### Tutorial Room +How the song boots work? +### Room 1 +1 cow? +### Room 2 +1 bee? +### Room 3 +1 cow 1 bee? +### Room 4 +1 cow 2 bees? +### Room 5 +lying chests? +### Room 6 (extra room) +you fell for the lying chest +your reward: 2 cows 3 bees +### Spells +stun: stuns enemies +buff: gives you more movement +talk to chest: you talk to chest +## Lore +### All chests have song boots +They see you already have them on so they talk to you +### Why are the chests talking? +Because the developer played souls dark and there was a message with "friend ahead" prompt in front of a mimic and thought that she wanted to be friends with the mimics +### The boots overheat you gonna take em off + +### Why song boots? +The golden piece will give you a way but an unconventional way From 9f38007e6b5074d68322855f6a190f02755858a7 Mon Sep 17 00:00:00 2001 From: Haigsov Date: Sun, 7 Apr 2024 21:22:34 -0400 Subject: [PATCH 18/86] Updated Maze.md --- The Maze.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/The Maze.md b/The Maze.md index 284f149..ceecaf5 100644 --- a/The Maze.md +++ b/The Maze.md @@ -1,7 +1,21 @@ -# Main Gameplay loop +# To do +Levels (easy to make) +## puzzle ideas +Every code is unique +combo puzzle (3 or 4 inputs) +missing rooms (you go from 22 to 24 and you're like oh where 23?) +backtracking to solve in another room +giving items to NPCs (you unlock shit from other rooms and give it to other NPCs) +rooms in jumbled order (1 -> 7 -> 12 -> 3) +#### binary type code +1. Binary code history hud +2. Are we expecting the player to know this or do we teach them +3. How do we communicate this to the player +# Ignore everything below +## Main Gameplay loop Puzzle RPG interacting with NPCs and using their info to solve puzzles while also fighting enemies using grid movement turn based combat (similar to crypt of the necrodancer) and might have magic spells, might. -# Verbs (mechanics) +## Verbs (mechanics) Movement before boots Interacting (z) Movement after boots: 8 different types of sound 4 of them @@ -11,7 +25,7 @@ melee combat ### can be scrapped spells take off boots -# To Do +## To Do ## Game What type of sounds do we want? 8 notes on a scale from a particular sound can be an instrument How de we translate to the player what the sounds do? Chests tell you? should be done in first room? From e94a094090b43a5ab04f6aa9e10c5cfad1fbb022 Mon Sep 17 00:00:00 2001 From: Tigran <122690491+TigranExe@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:54:15 -0400 Subject: [PATCH 19/86] Rework to add room specific stairs -New function to go to next map -New dictionary with assigned maps -Stairs now seperate scene from tilemap that can be assigned a map to go to For future: -Leftover cool code I felt wrong to delete -Just keep the heads up for others to add their level to Main's map_room_id_dict --- docs/contributing.md | 2 +- src/main/main.gd | 20 +++++++++++++++++++- src/maps/map-1.tscn | 9 +++++++-- src/maps/map-2.tscn | 12 ++++++++++-- src/maps/map-3.tscn | 12 ++++++++++-- src/maps/map.gd | 1 + src/player/player.gd | 4 ++-- src/scene-tiles/stairs/stairs.gd | 1 + src/scene-tiles/stairs/stairs.tscn | 2 ++ 9 files changed, 53 insertions(+), 10 deletions(-) diff --git a/docs/contributing.md b/docs/contributing.md index 97deb1a..d5653e6 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -16,4 +16,4 @@ - Each Scene should do one thing, each function should do one thing - Make [static classes](https://godottutorials.com/courses/introduction-to-gdscript/godot-tutorials-gdscript-20/) when able. - If a custom class/node doesn't have a position on screen or is instanced then removed, then pass it into the script as a object instead of putting in in the scene tree. -- ^ reach out to jayden if you need elaboration on this one \ No newline at end of file +- ^ reach out to jayden if you need elaboration on this one diff --git a/src/main/main.gd b/src/main/main.gd index 03da977..eabe0e6 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -7,6 +7,11 @@ extends Node2D var in_cutscene := false var maps:Array = [preload('res://src/maps/map-1.tscn'),preload('res://src/maps/map-2.tscn'),preload('res://src/maps/map-3.tscn')] +var map_room_id_dict: Dictionary = { #Not perfect but works for time constraint + 1 : preload('res://src/maps/map-1.tscn'), + 2: preload('res://src/maps/map-2.tscn'), + 3: preload('res://src/maps/map-3.tscn') +} var shuffled_maps:Array = [] var current_map_id @@ -14,7 +19,20 @@ var current_map_id func _ready() -> void: ui.text_rendered.connect(_start_cutscene) ui.text_removed.connect(_end_cutscene) - player.walked_into_stairs.connect(swap_map) + player.walked_into_stairs.connect(next_map) + pass + +func next_map(given_room_id: int) -> void: + var next_map_id :int = given_room_id + var nextMap:Node2D = map_room_id_dict[next_map_id].instantiate() + #load new map + current_map.queue_free() + add_child(nextMap) + current_map = nextMap + + #move the player to the spawn point + var playerSpawnMarker:Marker2D = nextMap.get_node('PlayerSpawn') + player.position = playerSpawnMarker.position pass func swap_map() -> void: diff --git a/src/maps/map-1.tscn b/src/maps/map-1.tscn index 5699bf0..52d3adf 100644 --- a/src/maps/map-1.tscn +++ b/src/maps/map-1.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=3 format=3 uid="uid://deqm4to4ptnq0"] +[gd_scene load_steps=4 format=3 uid="uid://deqm4to4ptnq0"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_vosps"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_web8r"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_8x2ye"] [node name="Map" type="Node2D"] script = ExtResource("1_web8r") @@ -10,8 +11,12 @@ script = ExtResource("1_web8r") tile_set = ExtResource("1_vosps") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 196615, 3, 262144, 393226, 3, 196608) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 196615, 3, 262144) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 48) + +[node name="stairs" parent="." instance=ExtResource("3_8x2ye")] +position = Vector2(160, 96) +toward_room_id = 2 diff --git a/src/maps/map-2.tscn b/src/maps/map-2.tscn index edb017b..96ad0c4 100644 --- a/src/maps/map-2.tscn +++ b/src/maps/map-2.tscn @@ -1,15 +1,23 @@ -[gd_scene load_steps=2 format=3 uid="uid://cwxdotd7hh5tb"] +[gd_scene load_steps=4 format=3 uid="uid://cwxdotd7hh5tb"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_2mk3g"] +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_wfc8d"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_wvxh7"] [node name="Map" type="Node2D"] +script = ExtResource("1_wfc8d") +room_id = 2 [node name="TileMap" type="TileMap" parent="."] tile_set = ExtResource("1_2mk3g") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 393219, 3, 196608, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) + +[node name="stairs" parent="." instance=ExtResource("3_wvxh7")] +position = Vector2(160, 96) +toward_room_id = 3 diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn index 192567e..8ca8799 100644 --- a/src/maps/map-3.tscn +++ b/src/maps/map-3.tscn @@ -1,15 +1,23 @@ -[gd_scene load_steps=2 format=3 uid="uid://bapnj7ekqfb0t"] +[gd_scene load_steps=4 format=3 uid="uid://bapnj7ekqfb0t"] +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_kwl2f"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_xfyi1"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_vucpd"] [node name="Map" type="Node2D"] +script = ExtResource("1_kwl2f") +room_id = 3 [node name="TileMap" type="TileMap" parent="."] tile_set = ExtResource("1_xfyi1") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458762, 262145, 18, 458761, 262145, 18, 65550, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 262157, 262145, 18, 196621, 262145, 18, 196620, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 327688, 262145, 18, 393224, 262145, 18, 393223, 262145, 18, 327687, 262145, 18, 327686, 262145, 18, 262150, 262145, 18, 196614, 262145, 18, 196613, 262145, 18, 196612, 262145, 18, 262148, 262145, 18, 262147, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 327685, 262145, 18, 393225, 262145, 18, 393226, 262145, 18, 393227, 262145, 18, 393228, 262145, 18, 393229, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 327693, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 196615, 262145, 18, 262151, 262145, 18, 131082, 3, 262144, 327692, 3, 196608) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458762, 262145, 18, 458761, 262145, 18, 65550, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 262157, 262145, 18, 196621, 262145, 18, 196620, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 327688, 262145, 18, 393224, 262145, 18, 393223, 262145, 18, 327687, 262145, 18, 327686, 262145, 18, 262150, 262145, 18, 196614, 262145, 18, 196613, 262145, 18, 196612, 262145, 18, 262148, 262145, 18, 262147, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 327685, 262145, 18, 393225, 262145, 18, 393226, 262145, 18, 393227, 262145, 18, 393229, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 327693, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 196615, 262145, 18, 262151, 262145, 18, 131082, 3, 262144, 524300, 1245185, 2, 393228, 262145, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(144, 48) + +[node name="stairs" parent="." instance=ExtResource("3_vucpd")] +position = Vector2(192, 80) +toward_room_id = 1 diff --git a/src/maps/map.gd b/src/maps/map.gd index d392bb2..52bbc82 100644 --- a/src/maps/map.gd +++ b/src/maps/map.gd @@ -3,6 +3,7 @@ extends Node2D # we need to add a collision shape to the tilemap for the player raycast to be able to detect it, otherwise it'll be considered null. + @onready var tilemap:TileMap = $TileMap func _ready() -> void: tilemap.add_to_group('wall') diff --git a/src/player/player.gd b/src/player/player.gd index 9a5a421..6929468 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -4,7 +4,7 @@ extends Area2D @onready var boots_packed_scene: PackedScene = preload("res://src/boots/boots.tscn") @onready var raycast := $RayCast2D -signal walked_into_stairs +signal walked_into_stairs(toward_which_room_id) signal moved(dir) const TILE_SIZE := 16 @@ -61,7 +61,7 @@ func check_next_tile(tile: Object) -> void: if tile == null: return if tile.is_in_group('stairs'): - walked_into_stairs.emit() + walked_into_stairs.emit(tile.toward_room_id) func _interact() -> void: raycast.force_raycast_update() diff --git a/src/scene-tiles/stairs/stairs.gd b/src/scene-tiles/stairs/stairs.gd index b57aeb8..4ea5add 100644 --- a/src/scene-tiles/stairs/stairs.gd +++ b/src/scene-tiles/stairs/stairs.gd @@ -1,5 +1,6 @@ extends Area2D +@export var toward_room_id: int = 0 # Called when the node enters the scene tree for the first time. func _ready() -> void: diff --git a/src/scene-tiles/stairs/stairs.tscn b/src/scene-tiles/stairs/stairs.tscn index 64e00e9..e8a68c7 100644 --- a/src/scene-tiles/stairs/stairs.tscn +++ b/src/scene-tiles/stairs/stairs.tscn @@ -10,9 +10,11 @@ size = Vector2(16, 16) script = ExtResource("1_ww3tu") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(8, 8) shape = SubResource("RectangleShape2D_8vrfj") [node name="Sprite2D" type="Sprite2D" parent="."] texture = ExtResource("1_cirol") +offset = Vector2(8, 8) region_enabled = true region_rect = Rect2(48, 96, 16, 16) From cc813814a536fb611da9e81380df58447f26e00a Mon Sep 17 00:00:00 2001 From: JUB_Yoush Date: Wed, 10 Apr 2024 21:41:06 -0400 Subject: [PATCH 20/86] dialog manager implemented --- addons/dialogue_manager/DialogueManager.cs | 394 ++++ addons/dialogue_manager/LICENSE | 21 + addons/dialogue_manager/assets/icon.svg | 52 + .../dialogue_manager/assets/icon.svg.import | 38 + .../assets/responses_menu.svg | 52 + .../assets/responses_menu.svg.import | 38 + addons/dialogue_manager/assets/update.svg | 71 + .../dialogue_manager/assets/update.svg.import | 37 + .../dialogue_manager/components/code_edit.gd | 425 ++++ .../components/code_edit.tscn | 56 + .../code_edit_syntax_highlighter.gd | 382 ++++ .../components/dialogue_cache.gd | 160 ++ .../components/download_update_panel.gd | 84 + .../components/download_update_panel.tscn | 60 + .../components/errors_panel.gd | 85 + .../components/errors_panel.tscn | 56 + .../dialogue_manager/components/files_list.gd | 144 ++ .../components/files_list.tscn | 40 + .../components/find_in_files.gd | 229 +++ .../components/find_in_files.tscn | 139 ++ .../components/parse_result.gd | 10 + addons/dialogue_manager/components/parser.gd | 1780 +++++++++++++++++ .../components/resolved_line_data.gd | 15 + .../components/resolved_tag_data.gd | 10 + .../components/search_and_replace.gd | 210 ++ .../components/search_and_replace.tscn | 87 + .../dialogue_manager/components/title_list.gd | 67 + .../components/title_list.tscn | 45 + .../components/update_button.gd | 126 ++ .../components/update_button.tscn | 42 + addons/dialogue_manager/constants.gd | 187 ++ addons/dialogue_manager/dialogue_label.gd | 226 +++ addons/dialogue_manager/dialogue_label.tscn | 19 + addons/dialogue_manager/dialogue_line.gd | 98 + addons/dialogue_manager/dialogue_manager.gd | 1235 ++++++++++++ .../dialogue_reponses_menu.gd | 131 ++ addons/dialogue_manager/dialogue_resource.gd | 42 + addons/dialogue_manager/dialogue_response.gd | 62 + .../editor_translation_parser_plugin.gd | 43 + .../example_balloon/ExampleBalloon.cs | 204 ++ .../example_balloon/example_balloon.gd | 141 ++ .../example_balloon/example_balloon.tscn | 149 ++ .../small_example_balloon.tscn | 173 ++ addons/dialogue_manager/import_plugin.gd | 113 ++ addons/dialogue_manager/l10n/en.mo | Bin 0 -> 9770 bytes addons/dialogue_manager/l10n/en.po | 481 +++++ addons/dialogue_manager/l10n/es.po | 457 +++++ addons/dialogue_manager/l10n/translations.pot | 471 +++++ addons/dialogue_manager/l10n/zh.po | 408 ++++ addons/dialogue_manager/l10n/zh_TW.po | 408 ++++ addons/dialogue_manager/plugin.cfg | 7 + addons/dialogue_manager/plugin.gd | 276 +++ addons/dialogue_manager/settings.gd | 184 ++ addons/dialogue_manager/test_scene.gd | 31 + addons/dialogue_manager/test_scene.tscn | 7 + addons/dialogue_manager/utilities/builtins.gd | 468 +++++ addons/dialogue_manager/views/main_view.gd | 1100 ++++++++++ addons/dialogue_manager/views/main_view.tscn | 334 ++++ .../dialogue_manager/views/settings_view.gd | 280 +++ .../dialogue_manager/views/settings_view.tscn | 221 ++ project.godot | 31 + src/autoloads/player_state.gd | 21 + src/dialogue/main.dialogue | 11 + src/dialogue/main.dialogue.import | 15 + src/main/main.gd | 1 + src/maps/map-1.tscn | 10 +- src/maps/map-4.tscn | 17 + src/player/player.gd | 11 +- src/scene-tiles/chest/chest.gd | 50 +- src/scene-tiles/chest/chest.tscn | 2 + 70 files changed, 13053 insertions(+), 27 deletions(-) create mode 100644 addons/dialogue_manager/DialogueManager.cs create mode 100644 addons/dialogue_manager/LICENSE create mode 100644 addons/dialogue_manager/assets/icon.svg create mode 100644 addons/dialogue_manager/assets/icon.svg.import create mode 100644 addons/dialogue_manager/assets/responses_menu.svg create mode 100644 addons/dialogue_manager/assets/responses_menu.svg.import create mode 100644 addons/dialogue_manager/assets/update.svg create mode 100644 addons/dialogue_manager/assets/update.svg.import create mode 100644 addons/dialogue_manager/components/code_edit.gd create mode 100644 addons/dialogue_manager/components/code_edit.tscn create mode 100644 addons/dialogue_manager/components/code_edit_syntax_highlighter.gd create mode 100644 addons/dialogue_manager/components/dialogue_cache.gd create mode 100644 addons/dialogue_manager/components/download_update_panel.gd create mode 100644 addons/dialogue_manager/components/download_update_panel.tscn create mode 100644 addons/dialogue_manager/components/errors_panel.gd create mode 100644 addons/dialogue_manager/components/errors_panel.tscn create mode 100644 addons/dialogue_manager/components/files_list.gd create mode 100644 addons/dialogue_manager/components/files_list.tscn create mode 100644 addons/dialogue_manager/components/find_in_files.gd create mode 100644 addons/dialogue_manager/components/find_in_files.tscn create mode 100644 addons/dialogue_manager/components/parse_result.gd create mode 100644 addons/dialogue_manager/components/parser.gd create mode 100644 addons/dialogue_manager/components/resolved_line_data.gd create mode 100644 addons/dialogue_manager/components/resolved_tag_data.gd create mode 100644 addons/dialogue_manager/components/search_and_replace.gd create mode 100644 addons/dialogue_manager/components/search_and_replace.tscn create mode 100644 addons/dialogue_manager/components/title_list.gd create mode 100644 addons/dialogue_manager/components/title_list.tscn create mode 100644 addons/dialogue_manager/components/update_button.gd create mode 100644 addons/dialogue_manager/components/update_button.tscn create mode 100644 addons/dialogue_manager/constants.gd create mode 100644 addons/dialogue_manager/dialogue_label.gd create mode 100644 addons/dialogue_manager/dialogue_label.tscn create mode 100644 addons/dialogue_manager/dialogue_line.gd create mode 100644 addons/dialogue_manager/dialogue_manager.gd create mode 100644 addons/dialogue_manager/dialogue_reponses_menu.gd create mode 100644 addons/dialogue_manager/dialogue_resource.gd create mode 100644 addons/dialogue_manager/dialogue_response.gd create mode 100644 addons/dialogue_manager/editor_translation_parser_plugin.gd create mode 100644 addons/dialogue_manager/example_balloon/ExampleBalloon.cs create mode 100644 addons/dialogue_manager/example_balloon/example_balloon.gd create mode 100644 addons/dialogue_manager/example_balloon/example_balloon.tscn create mode 100644 addons/dialogue_manager/example_balloon/small_example_balloon.tscn create mode 100644 addons/dialogue_manager/import_plugin.gd create mode 100644 addons/dialogue_manager/l10n/en.mo create mode 100644 addons/dialogue_manager/l10n/en.po create mode 100644 addons/dialogue_manager/l10n/es.po create mode 100644 addons/dialogue_manager/l10n/translations.pot create mode 100644 addons/dialogue_manager/l10n/zh.po create mode 100644 addons/dialogue_manager/l10n/zh_TW.po create mode 100644 addons/dialogue_manager/plugin.cfg create mode 100644 addons/dialogue_manager/plugin.gd create mode 100644 addons/dialogue_manager/settings.gd create mode 100644 addons/dialogue_manager/test_scene.gd create mode 100644 addons/dialogue_manager/test_scene.tscn create mode 100644 addons/dialogue_manager/utilities/builtins.gd create mode 100644 addons/dialogue_manager/views/main_view.gd create mode 100644 addons/dialogue_manager/views/main_view.tscn create mode 100644 addons/dialogue_manager/views/settings_view.gd create mode 100644 addons/dialogue_manager/views/settings_view.tscn create mode 100644 src/autoloads/player_state.gd create mode 100644 src/dialogue/main.dialogue create mode 100644 src/dialogue/main.dialogue.import create mode 100644 src/maps/map-4.tscn diff --git a/addons/dialogue_manager/DialogueManager.cs b/addons/dialogue_manager/DialogueManager.cs new file mode 100644 index 0000000..ae4f931 --- /dev/null +++ b/addons/dialogue_manager/DialogueManager.cs @@ -0,0 +1,394 @@ +using Godot; +using Godot.Collections; +using System; +using System.Reflection; +using System.Threading.Tasks; + +#nullable enable + +namespace DialogueManagerRuntime +{ + public enum TranslationSource + { + None, + Guess, + CSV, + PO + } + + public partial class DialogueManager : Node + { + public delegate void PassedTitleEventHandler(string title); + public delegate void GotDialogueEventHandler(DialogueLine dialogueLine); + public delegate void MutatedEventHandler(Dictionary mutation); + public delegate void DialogueEndedEventHandler(Resource dialogueResource); + + public static PassedTitleEventHandler? PassedTitle; + public static GotDialogueEventHandler? GotDialogue; + public static MutatedEventHandler? Mutated; + public static DialogueEndedEventHandler? DialogueEnded; + + [Signal] public delegate void ResolvedEventHandler(Variant value); + + private static GodotObject? instance; + public static GodotObject Instance + { + get + { + if (instance == null) + { + instance = Engine.GetSingleton("DialogueManager"); + } + return instance; + } + } + + + public static Godot.Collections.Array GameStates + { + get => (Godot.Collections.Array)Instance.Get("game_states"); + set => Instance.Set("game_states", value); + } + + + public static bool IncludeSingletons + { + get => (bool)Instance.Get("include_singletons"); + set => Instance.Set("include_singletons", value); + } + + + public static bool IncludeClasses + { + get => (bool)Instance.Get("include_classes"); + set => Instance.Set("include_classes", value); + } + + + public static TranslationSource TranslationSource + { + get => (TranslationSource)(int)Instance.Get("translation_source"); + set => Instance.Set("translation_source", (int)value); + } + + + public static Func GetCurrentScene + { + set => Instance.Set("get_current_scene", Callable.From(value)); + } + + + public void Prepare() + { + Instance.Connect("passed_title", Callable.From((string title) => PassedTitle?.Invoke(title))); + Instance.Connect("got_dialogue", Callable.From((RefCounted line) => GotDialogue?.Invoke(new DialogueLine(line)))); + Instance.Connect("mutated", Callable.From((Dictionary mutation) => Mutated?.Invoke(mutation))); + Instance.Connect("dialogue_ended", Callable.From((Resource dialogueResource) => DialogueEnded?.Invoke(dialogueResource))); + } + + + public static async Task GetSingleton() + { + if (instance != null) return instance; + + var tree = Engine.GetMainLoop(); + int x = 0; + + // Try and find the singleton for a few seconds + while (!Engine.HasSingleton("DialogueManager") && x < 300) + { + await tree.ToSignal(tree, SceneTree.SignalName.ProcessFrame); + x++; + } + + // If it times out something is wrong + if (x >= 300) + { + throw new Exception("The DialogueManager singleton is missing."); + } + + instance = Engine.GetSingleton("DialogueManager"); + return instance; + } + + public static async Task GetNextDialogueLine(Resource dialogueResource, string key = "", Array? extraGameStates = null) + { + Instance.Call("_bridge_get_next_dialogue_line", dialogueResource, key, extraGameStates ?? new Array()); + var result = await Instance.ToSignal(Instance, "bridge_get_next_dialogue_line_completed"); + + if ((RefCounted)result[0] == null) return null; + + return new DialogueLine((RefCounted)result[0]); + } + + + public static CanvasLayer ShowExampleDialogueBalloon(Resource dialogueResource, string key = "", Array? extraGameStates = null) + { + return (CanvasLayer)Instance.Call("show_example_dialogue_balloon", dialogueResource, key, extraGameStates ?? new Array()); + } + + + public static Node ShowDialogueBalloonScene(string balloonScene, Resource dialogueResource, string key = "", Array? extraGameStates = null) + { + return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array()); + } + + public static Node ShowDialogueBalloonScene(PackedScene balloonScene, Resource dialogueResource, string key = "", Array? extraGameStates = null) + { + return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array()); + } + + public static Node ShowDialogueBalloonScene(Node balloonScene, Resource dialogueResource, string key = "", Array? extraGameStates = null) + { + return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array()); + } + + + public static Node ShowDialogueBalloon(Resource dialogueResource, string key = "", Array? extraGameStates = null) + { + return (Node)Instance.Call("show_dialogue_balloon", dialogueResource, key, extraGameStates ?? new Array()); + } + + + public static async void Mutate(Dictionary mutation, Array? extraGameStates = null, bool isInlineMutation = false) + { + Instance.Call("_bridge_mutate", mutation, extraGameStates ?? new Array(), isInlineMutation); + await Instance.ToSignal(Instance, "bridge_mutated"); + } + + + public bool ThingHasMethod(GodotObject thing, string method) + { + MethodInfo? info = thing.GetType().GetMethod(method, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); + return info != null; + } + + + public async void ResolveThingMethod(GodotObject thing, string method, Array args) + { + MethodInfo? info = thing.GetType().GetMethod(method, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); + + if (info == null) return; + +#nullable disable + // Convert the method args to something reflection can handle + ParameterInfo[] argTypes = info.GetParameters(); + object[] _args = new object[argTypes.Length]; + for (int i = 0; i < argTypes.Length; i++) + { + if (i < args.Count && args[i].Obj != null) + { + _args[i] = Convert.ChangeType(args[i].Obj, argTypes[i].ParameterType); + } + else if (argTypes[i].DefaultValue != null) + { + _args[i] = argTypes[i].DefaultValue; + } + } + + // Add a single frame wait in case the method returns before signals can listen + await ToSignal(Engine.GetMainLoop(), SceneTree.SignalName.ProcessFrame); + + if (info.ReturnType == typeof(Task)) + { + await (Task)info.Invoke(thing, _args); + EmitSignal(SignalName.Resolved, null); + } + else + { + var value = (Variant)info.Invoke(thing, _args); + EmitSignal(SignalName.Resolved, value); + } + } +#nullable enable + } + + + public partial class DialogueLine : RefCounted + { + private string type = "dialogue"; + public string Type + { + get => type; + set => type = value; + } + + private string next_id = ""; + public string NextId + { + get => next_id; + set => next_id = value; + } + + private string character = ""; + public string Character + { + get => character; + set => character = value; + } + + private string text = ""; + public string Text + { + get => text; + set => text = value; + } + + private string translation_key = ""; + public string TranslationKey + { + get => translation_key; + set => translation_key = value; + } + + private Array responses = new Array(); + public Array Responses + { + get => responses; + } + + private string? time = null; + public string? Time + { + get => time; + } + + private Dictionary pauses = new Dictionary(); + public Dictionary Pauses + { + get => pauses; + } + + private Dictionary speeds = new Dictionary(); + public Dictionary Speeds + { + get => speeds; + } + + private Array inline_mutations = new Array(); + public Array InlineMutations + { + get => inline_mutations; + } + + private Array extra_game_states = new Array(); + + private Array tags = new Array(); + public Array Tags + { + get => tags; + } + + public DialogueLine(RefCounted data) + { + type = (string)data.Get("type"); + next_id = (string)data.Get("next_id"); + character = (string)data.Get("character"); + text = (string)data.Get("text"); + translation_key = (string)data.Get("translation_key"); + pauses = (Dictionary)data.Get("pauses"); + speeds = (Dictionary)data.Get("speeds"); + inline_mutations = (Array)data.Get("inline_mutations"); + time = (string)data.Get("time"); + tags = (Array)data.Get("tags"); + + foreach (var response in (Array)data.Get("responses")) + { + responses.Add(new DialogueResponse(response)); + } + } + + + public string GetTagValue(string tagName) + { + string wrapped = $"{tagName}="; + foreach (var tag in tags) + { + if (tag.StartsWith(wrapped)) + { + return tag.Substring(wrapped.Length); + } + } + return ""; + } + + public override string ToString() + { + switch (type) + { + case "dialogue": + return $""; + case "mutation": + return ""; + default: + return ""; + } + } + } + + + public partial class DialogueResponse : RefCounted + { + private string next_id = ""; + public string NextId + { + get => next_id; + set => next_id = value; + } + + private bool is_allowed = true; + public bool IsAllowed + { + get => is_allowed; + set => is_allowed = value; + } + + private string text = ""; + public string Text + { + get => text; + set => text = value; + } + + private string translation_key = ""; + public string TranslationKey + { + get => translation_key; + set => translation_key = value; + } + + private Array tags = new Array(); + public Array Tags + { + get => tags; + } + + public DialogueResponse(RefCounted data) + { + next_id = (string)data.Get("next_id"); + is_allowed = (bool)data.Get("is_allowed"); + text = (string)data.Get("text"); + translation_key = (string)data.Get("translation_key"); + tags = (Array)data.Get("tags"); + } + + public string GetTagValue(string tagName) + { + string wrapped = $"{tagName}="; + foreach (var tag in tags) + { + if (tag.StartsWith(wrapped)) + { + return tag.Substring(wrapped.Length); + } + } + return ""; + } + + public override string ToString() + { + return $" + + + + + + + + + diff --git a/addons/dialogue_manager/assets/icon.svg.import b/addons/dialogue_manager/assets/icon.svg.import new file mode 100644 index 0000000..3b6fd5e --- /dev/null +++ b/addons/dialogue_manager/assets/icon.svg.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d3lr2uas6ax8v" +path="res://.godot/imported/icon.svg-17eb5d3e2a3cfbe59852220758c5b7bd.ctex" +metadata={ +"has_editor_variant": true, +"vram_texture": false +} + +[deps] + +source_file="res://addons/dialogue_manager/assets/icon.svg" +dest_files=["res://.godot/imported/icon.svg-17eb5d3e2a3cfbe59852220758c5b7bd.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=true +editor/convert_colors_with_editor_theme=true diff --git a/addons/dialogue_manager/assets/responses_menu.svg b/addons/dialogue_manager/assets/responses_menu.svg new file mode 100644 index 0000000..4e4089d --- /dev/null +++ b/addons/dialogue_manager/assets/responses_menu.svg @@ -0,0 +1,52 @@ + + + + + + + + + + diff --git a/addons/dialogue_manager/assets/responses_menu.svg.import b/addons/dialogue_manager/assets/responses_menu.svg.import new file mode 100644 index 0000000..83355fc --- /dev/null +++ b/addons/dialogue_manager/assets/responses_menu.svg.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://drjfciwitjm83" +path="res://.godot/imported/responses_menu.svg-87cf63ca685d53616205049572f4eb8f.ctex" +metadata={ +"has_editor_variant": true, +"vram_texture": false +} + +[deps] + +source_file="res://addons/dialogue_manager/assets/responses_menu.svg" +dest_files=["res://.godot/imported/responses_menu.svg-87cf63ca685d53616205049572f4eb8f.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=true +editor/convert_colors_with_editor_theme=true diff --git a/addons/dialogue_manager/assets/update.svg b/addons/dialogue_manager/assets/update.svg new file mode 100644 index 0000000..a5b80ee --- /dev/null +++ b/addons/dialogue_manager/assets/update.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + diff --git a/addons/dialogue_manager/assets/update.svg.import b/addons/dialogue_manager/assets/update.svg.import new file mode 100644 index 0000000..2d8171a --- /dev/null +++ b/addons/dialogue_manager/assets/update.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d3baj6rygkb3f" +path="res://.godot/imported/update.svg-f1628866ed4eb2e13e3b81f75443687e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/dialogue_manager/assets/update.svg" +dest_files=["res://.godot/imported/update.svg-f1628866ed4eb2e13e3b81f75443687e.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 diff --git a/addons/dialogue_manager/components/code_edit.gd b/addons/dialogue_manager/components/code_edit.gd new file mode 100644 index 0000000..e57c1af --- /dev/null +++ b/addons/dialogue_manager/components/code_edit.gd @@ -0,0 +1,425 @@ +@tool +extends CodeEdit + + +signal active_title_change(title: String) +signal error_clicked(line_number: int) +signal external_file_requested(path: String, title: String) + + +const DialogueSyntaxHighlighter = preload("./code_edit_syntax_highlighter.gd") + + +# A link back to the owner MainView +var main_view + +# Theme overrides for syntax highlighting, etc +var theme_overrides: Dictionary: + set(value): + theme_overrides = value + + syntax_highlighter = DialogueSyntaxHighlighter.new() + + # General UI + add_theme_color_override("font_color", theme_overrides.text_color) + add_theme_color_override("background_color", theme_overrides.background_color) + add_theme_color_override("current_line_color", theme_overrides.current_line_color) + add_theme_font_override("font", get_theme_font("source", "EditorFonts")) + add_theme_font_size_override("font_size", theme_overrides.font_size * theme_overrides.scale) + font_size = round(theme_overrides.font_size) + get: + return theme_overrides + +# Any parse errors +var errors: Array: + set(next_errors): + errors = next_errors + for i in range(0, get_line_count()): + var is_error: bool = false + for error in errors: + if error.line_number == i: + is_error = true + mark_line_as_error(i, is_error) + _on_code_edit_caret_changed() + get: + return errors + +# The last selection (if there was one) so we can remember it for refocusing +var last_selected_text: String + +var font_size: int: + set(value): + font_size = value + add_theme_font_size_override("font_size", font_size * theme_overrides.scale) + get: + return font_size + +var WEIGHTED_RANDOM_PREFIX: RegEx = RegEx.create_from_string("^\\%[\\d.]+\\s") + + +func _ready() -> void: + # Add error gutter + add_gutter(0) + set_gutter_type(0, TextEdit.GUTTER_TYPE_ICON) + + # Add comment delimiter + if not has_comment_delimiter("#"): + add_comment_delimiter("#", "", true) + + syntax_highlighter = DialogueSyntaxHighlighter.new() + + +func _gui_input(event: InputEvent) -> void: + if event is InputEventKey and event.is_pressed(): + match event.as_text(): + "Ctrl+Equal", "Command+Equal": + self.font_size += 1 + get_viewport().set_input_as_handled() + "Ctrl+Minus", "Command+Minus": + self.font_size -= 1 + get_viewport().set_input_as_handled() + "Ctrl+0", "Command+0": + self.font_size = theme_overrides.font_size + get_viewport().set_input_as_handled() + "Ctrl+K", "Command+K": + toggle_comment() + get_viewport().set_input_as_handled() + "Alt+Up": + move_line(-1) + get_viewport().set_input_as_handled() + "Alt+Down": + move_line(1) + get_viewport().set_input_as_handled() + + elif event is InputEventMouse: + match event.as_text(): + "Ctrl+Mouse Wheel Up", "Command+Mouse Wheel Up": + self.font_size += 1 + get_viewport().set_input_as_handled() + "Ctrl+Mouse Wheel Down", "Command+Mouse Wheel Down": + self.font_size -= 1 + get_viewport().set_input_as_handled() + + +func _can_drop_data(at_position: Vector2, data) -> bool: + if typeof(data) != TYPE_DICTIONARY: return false + if data.type != "files": return false + + var files: PackedStringArray = Array(data.files).filter(func(f): return f.get_extension() == "dialogue") + return files.size() > 0 + + +func _drop_data(at_position: Vector2, data) -> void: + var replace_regex: RegEx = RegEx.create_from_string("[^a-zA-Z_0-9]+") + + var files: PackedStringArray = Array(data.files).filter(func(f): return f.get_extension() == "dialogue") + for file in files: + # Don't import the file into itself + if file == main_view.current_file_path: continue + + var path = file.replace("res://", "").replace(".dialogue", "") + # Find the first non-import line in the file to add our import + var lines = text.split("\n") + for i in range(0, lines.size()): + if not lines[i].begins_with("import "): + insert_line_at(i, "import \"%s\" as %s\n" % [file, replace_regex.sub(path, "_", true)]) + set_caret_line(i) + break + + +func _request_code_completion(force: bool) -> void: + var cursor: Vector2 = get_cursor() + var current_line: String = get_line(cursor.y) + + if ("=> " in current_line or "=>< " in current_line) and (cursor.x > current_line.find("=>")): + var prompt: String = current_line.split("=>")[1] + if prompt.begins_with("< "): + prompt = prompt.substr(2) + else: + prompt = prompt.substr(1) + + if "=> " in current_line: + if matches_prompt(prompt, "end"): + add_code_completion_option(CodeEdit.KIND_CLASS, "END", "END".substr(prompt.length()), theme_overrides.text_color, get_theme_icon("Stop", "EditorIcons")) + if matches_prompt(prompt, "end!"): + add_code_completion_option(CodeEdit.KIND_CLASS, "END!", "END!".substr(prompt.length()), theme_overrides.text_color, get_theme_icon("Stop", "EditorIcons")) + + # Get all titles, including those in imports + var parser: DialogueManagerParser = DialogueManagerParser.new() + parser.prepare(text, main_view.current_file_path, false) + for title in parser.titles: + if "/" in title: + var bits = title.split("/") + if matches_prompt(prompt, bits[0]) or matches_prompt(prompt, bits[1]): + add_code_completion_option(CodeEdit.KIND_CLASS, title, title.substr(prompt.length()), theme_overrides.text_color, get_theme_icon("CombineLines", "EditorIcons")) + elif matches_prompt(prompt, title): + add_code_completion_option(CodeEdit.KIND_CLASS, title, title.substr(prompt.length()), theme_overrides.text_color, get_theme_icon("ArrowRight", "EditorIcons")) + update_code_completion_options(true) + parser.free() + return + + var name_so_far: String = WEIGHTED_RANDOM_PREFIX.sub(current_line.strip_edges(), "") + if name_so_far != "" and name_so_far[0].to_upper() == name_so_far[0]: + # Only show names starting with that character + var names: PackedStringArray = get_character_names(name_so_far) + if names.size() > 0: + for name in names: + add_code_completion_option(CodeEdit.KIND_CLASS, name + ": ", name.substr(name_so_far.length()) + ": ", theme_overrides.text_color, get_theme_icon("Sprite2D", "EditorIcons")) + update_code_completion_options(true) + else: + cancel_code_completion() + + +func _filter_code_completion_candidates(candidates: Array) -> Array: + # Not sure why but if this method isn't overridden then all completions are wrapped in quotes. + return candidates + + +func _confirm_code_completion(replace: bool) -> void: + var completion = get_code_completion_option(get_code_completion_selected_index()) + begin_complex_operation() + # Delete any part of the text that we've already typed + for i in range(0, completion.display_text.length() - completion.insert_text.length()): + backspace() + # Insert the whole match + insert_text_at_caret(completion.display_text) + end_complex_operation() + + # Close the autocomplete menu on the next tick + call_deferred("cancel_code_completion") + + +### Helpers + + +# Get the current caret as a Vector2 +func get_cursor() -> Vector2: + return Vector2(get_caret_column(), get_caret_line()) + + +# Set the caret from a Vector2 +func set_cursor(from_cursor: Vector2) -> void: + set_caret_line(from_cursor.y) + set_caret_column(from_cursor.x) + + +# Check if a prompt is the start of a string without actually being that string +func matches_prompt(prompt: String, matcher: String) -> bool: + return prompt.length() < matcher.length() and matcher.to_lower().begins_with(prompt.to_lower()) + + +## Get a list of titles from the current text +func get_titles() -> PackedStringArray: + var titles = PackedStringArray([]) + var lines = text.split("\n") + for line in lines: + if line.begins_with("~ "): + titles.append(line.substr(2).strip_edges()) + return titles + + +## Work out what the next title above the current line is +func check_active_title() -> void: + var line_number = get_caret_line() + var lines = text.split("\n") + # Look at each line above this one to find the next title line + for i in range(line_number, -1, -1): + if lines[i].begins_with("~ "): + active_title_change.emit(lines[i].replace("~ ", "")) + return + + active_title_change.emit("") + + +# Move the caret line to match a given title +func go_to_title(title: String) -> void: + var lines = text.split("\n") + for i in range(0, lines.size()): + if lines[i].strip_edges() == "~ " + title: + set_caret_line(i) + center_viewport_to_caret() + + +func get_character_names(beginning_with: String) -> PackedStringArray: + var names: PackedStringArray = [] + var lines = text.split("\n") + for line in lines: + if ": " in line: + var name: String = WEIGHTED_RANDOM_PREFIX.sub(line.split(": ")[0].strip_edges(), "") + if not name in names and matches_prompt(beginning_with, name): + names.append(name) + return names + + +# Mark a line as an error or not +func mark_line_as_error(line_number: int, is_error: bool) -> void: + if is_error: + set_line_background_color(line_number, theme_overrides.error_line_color) + set_line_gutter_icon(line_number, 0, get_theme_icon("StatusError", "EditorIcons")) + else: + set_line_background_color(line_number, theme_overrides.background_color) + set_line_gutter_icon(line_number, 0, null) + + +# Insert or wrap some bbcode at the caret/selection +func insert_bbcode(open_tag: String, close_tag: String = "") -> void: + if close_tag == "": + insert_text_at_caret(open_tag) + grab_focus() + else: + var selected_text = get_selected_text() + insert_text_at_caret("%s%s%s" % [open_tag, selected_text, close_tag]) + grab_focus() + set_caret_column(get_caret_column() - close_tag.length()) + +# Insert text at current caret position +# Move Caret down 1 line if not => END +func insert_text(text: String) -> void: + if text != "=> END": + insert_text_at_caret(text+"\n") + set_caret_line(get_caret_line()+1) + else: + insert_text_at_caret(text) + grab_focus() + + +# Toggle the selected lines as comments +func toggle_comment() -> void: + begin_complex_operation() + + var comment_delimiter: String = delimiter_comments[0] + var is_first_line: bool = true + var will_comment: bool = true + var selections: Array = [] + var line_offsets: Dictionary = {} + + for caret_index in range(0, get_caret_count()): + var from_line: int = get_caret_line(caret_index) + var from_column: int = get_caret_column(caret_index) + var to_line: int = get_caret_line(caret_index) + var to_column: int = get_caret_column(caret_index) + + if has_selection(caret_index): + from_line = get_selection_from_line(caret_index) + to_line = get_selection_to_line(caret_index) + from_column = get_selection_from_column(caret_index) + to_column = get_selection_to_column(caret_index) + + selections.append({ + from_line = from_line, + from_column = from_column, + to_line = to_line, + to_column = to_column + }) + + for line_number in range(from_line, to_line + 1): + if line_offsets.has(line_number): continue + + var line_text: String = get_line(line_number) + + # The first line determines if we are commenting or uncommentingg + if is_first_line: + is_first_line = false + will_comment = not line_text.strip_edges().begins_with(comment_delimiter) + + # Only comment/uncomment if the current line needs to + if will_comment: + set_line(line_number, comment_delimiter + line_text) + line_offsets[line_number] = 1 + elif line_text.begins_with(comment_delimiter): + set_line(line_number, line_text.substr(comment_delimiter.length())) + line_offsets[line_number] = -1 + else: + line_offsets[line_number] = 0 + + for caret_index in range(0, get_caret_count()): + var selection: Dictionary = selections[caret_index] + select( + selection.from_line, + selection.from_column + line_offsets[selection.from_line], + selection.to_line, + selection.to_column + line_offsets[selection.to_line], + caret_index + ) + set_caret_column(selection.from_column + line_offsets[selection.from_line], false, caret_index) + + end_complex_operation() + + text_set.emit() + text_changed.emit() + + +# Move the selected lines up or down +func move_line(offset: int) -> void: + offset = clamp(offset, -1, 1) + + var cursor = get_cursor() + var reselect: bool = false + var from: int = cursor.y + var to: int = cursor.y + if has_selection(): + reselect = true + from = get_selection_from_line() + to = get_selection_to_line() + + var lines := text.split("\n") + + # We can't move the lines out of bounds + if from + offset < 0 or to + offset >= lines.size(): return + + var target_from_index = from - 1 if offset == -1 else to + 1 + var target_to_index = to if offset == -1 else from + var line_to_move = lines[target_from_index] + lines.remove_at(target_from_index) + lines.insert(target_to_index, line_to_move) + + text = "\n".join(lines) + + cursor.y += offset + from += offset + to += offset + if reselect: + select(from, 0, to, get_line_width(to)) + set_cursor(cursor) + text_changed.emit() + + +### Signals + + +func _on_code_edit_symbol_validate(symbol: String) -> void: + if symbol.begins_with("res://") and symbol.ends_with(".dialogue"): + set_symbol_lookup_word_as_valid(true) + return + + for title in get_titles(): + if symbol == title: + set_symbol_lookup_word_as_valid(true) + return + set_symbol_lookup_word_as_valid(false) + + +func _on_code_edit_symbol_lookup(symbol: String, line: int, column: int) -> void: + if symbol.begins_with("res://") and symbol.ends_with(".dialogue"): + external_file_requested.emit(symbol, "") + else: + go_to_title(symbol) + + +func _on_code_edit_text_changed() -> void: + request_code_completion(true) + + +func _on_code_edit_text_set() -> void: + queue_redraw() + + +func _on_code_edit_caret_changed() -> void: + check_active_title() + last_selected_text = get_selected_text() + + +func _on_code_edit_gutter_clicked(line: int, gutter: int) -> void: + var line_errors = errors.filter(func(error): return error.line_number == line) + if line_errors.size() > 0: + error_clicked.emit(line) diff --git a/addons/dialogue_manager/components/code_edit.tscn b/addons/dialogue_manager/components/code_edit.tscn new file mode 100644 index 0000000..a974ea3 --- /dev/null +++ b/addons/dialogue_manager/components/code_edit.tscn @@ -0,0 +1,56 @@ +[gd_scene load_steps=4 format=3 uid="uid://civ6shmka5e8u"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit_syntax_highlighter.gd" id="1_58cfo"] +[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit.gd" id="1_g324i"] + +[sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_cobxx"] +script = ExtResource("1_58cfo") + +[node name="CodeEdit" type="CodeEdit"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +text = "~ title_thing + +if this = \"that\" or 'this' +Nathan: Something +- Then [if test.thing() == 2.0] => somewhere +- Other => END! + +~ somewhere + +set has_something = true +=> END" +highlight_all_occurrences = true +highlight_current_line = true +draw_tabs = true +syntax_highlighter = SubResource("SyntaxHighlighter_cobxx") +scroll_past_end_of_file = true +minimap_draw = true +symbol_lookup_on_click = true +line_folding = true +gutters_draw_line_numbers = true +gutters_draw_fold_gutter = true +delimiter_strings = Array[String](["\" \""]) +delimiter_comments = Array[String](["#"]) +code_completion_enabled = true +code_completion_prefixes = Array[String]([">", "<"]) +indent_automatic = true +auto_brace_completion_enabled = true +auto_brace_completion_highlight_matching = true +auto_brace_completion_pairs = { +"\"": "\"", +"(": ")", +"[": "]", +"{": "}" +} +script = ExtResource("1_g324i") + +[connection signal="caret_changed" from="." to="." method="_on_code_edit_caret_changed"] +[connection signal="gutter_clicked" from="." to="." method="_on_code_edit_gutter_clicked"] +[connection signal="symbol_lookup" from="." to="." method="_on_code_edit_symbol_lookup"] +[connection signal="symbol_validate" from="." to="." method="_on_code_edit_symbol_validate"] +[connection signal="text_changed" from="." to="." method="_on_code_edit_text_changed"] +[connection signal="text_set" from="." to="." method="_on_code_edit_text_set"] diff --git a/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd b/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd new file mode 100644 index 0000000..fe1b8bd --- /dev/null +++ b/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd @@ -0,0 +1,382 @@ +@tool +extends SyntaxHighlighter + + +enum ExpressionType {DO, SET, IF} + + +var dialogue_manager_parser: DialogueManagerParser = DialogueManagerParser.new() + +var regex_titles: RegEx = RegEx.create_from_string("^\\s*(?~\\s+[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+)") +var regex_comments: RegEx = RegEx.create_from_string("(?:(?>\"(?:\\\\\"|[^\"\\n])*\")[^\"\\n]*?\\s*(?<comment>#[^\\n]*)$|^[^\"#\\n]*?\\s*(?<comment2>#[^\\n]*))") +var regex_mutation: RegEx = RegEx.create_from_string("^\\s*(do|do!|set) (?<mutation>.*)") +var regex_condition: RegEx = RegEx.create_from_string("^\\s*(if|elif|while|else if) (?<condition>.*)") +var regex_wcondition: RegEx = RegEx.create_from_string("\\[if (?<condition>((?:[^\\[\\]]*)|(?:\\[(?1)\\]))*?)\\]") +var regex_wendif: RegEx = RegEx.create_from_string("\\[(\\/if|else)\\]") +var regex_rgroup: RegEx = RegEx.create_from_string("\\[\\[(?<options>.*?)\\]\\]") +var regex_endconditions: RegEx = RegEx.create_from_string("^\\s*(endif|else):?\\s*$") +var regex_tags: RegEx = RegEx.create_from_string("\\[(?<tag>(?!(?:ID:.*)|if)[a-zA-Z_][a-zA-Z0-9_]*!?)(?:[= ](?<val>[^\\[\\]]+))?\\](?:(?<text>(?!\\[\\/\\k<tag>\\]).*?)?(?<end>\\[\\/\\k<tag>\\]))?") +var regex_dialogue: RegEx = RegEx.create_from_string("^\\s*(?:(?<random>\\%[\\d.]* )|(?<response>- ))?(?:(?<character>[^#:]*): )?(?<dialogue>.*)$") +var regex_goto: RegEx = RegEx.create_from_string("=><? (?:(?<file>[^\\/]+)\\/)?(?<title>[^\\/]*)") +var regex_string: RegEx = RegEx.create_from_string("^(?<delimiter>[\"'])(?<content>(?:\\\\{2})*|(?:.*?[^\\\\](?:\\\\{2})*))\\1$") +var regex_escape: RegEx = RegEx.create_from_string("\\\\.") +var regex_number: RegEx = RegEx.create_from_string("^-?(?:(?:0x(?:[0-9A-Fa-f]{2})+)|(?:0b[01]+)|(?:\\d+(?:(?:[\\.]\\d*)?(?:e\\d+)?)|(?:_\\d+)+)?)$") +var regex_array: RegEx = RegEx.create_from_string("\\[((?>[^\\[\\]]+|(?R))*)\\]") +var regex_dict: RegEx = RegEx.create_from_string("^\\{((?>[^\\{\\}]+|(?R))*)\\}$") +var regex_kvdict: RegEx = RegEx.create_from_string("^\\s*(?<left>.*?)\\s*(?<colon>:|=)\\s*(?<right>[^\\/]+)$") +var regex_commas: RegEx = RegEx.create_from_string("([^,]+)(?:\\s*,\\s*)?") +var regex_assignment: RegEx = RegEx.create_from_string("^\\s*(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*(?<op>(?:\\/|\\*|-|\\+)?=)\\s*(?<val>.*)$") +var regex_varname: RegEx = RegEx.create_from_string("^\\s*(?!true|false|and|or|not|in|null)(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*$") +var regex_keyword: RegEx = RegEx.create_from_string("^\\s*(true|false|null)\\s*$") +var regex_function: RegEx = RegEx.create_from_string("^\\s*([a-zA-Z_][a-zA-Z_0-9]*\\s*)\\(") +var regex_comparison: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s*(?<op>==|>=|<=|<|>|!=)\\s*(?<right>.*)$") +var regex_blogical: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s+(?<op>and|or|in)\\s+(?<right>.*)$") +var regex_ulogical: RegEx = RegEx.create_from_string("^\\s*(?<op>not)\\s+(?<right>.*)$") +var regex_paren: RegEx = RegEx.create_from_string("\\((?<paren>((?:[^\\(\\)]*)|(?:\\((?1)\\)))*?)\\)") + +var cache: Dictionary = {} + + +func _notification(what: int) -> void: + if what == NOTIFICATION_PREDELETE: + dialogue_manager_parser.free() + + +func _clear_highlighting_cache() -> void: + cache = {} + + +## Returns the syntax coloring for a dialogue file line +func _get_line_syntax_highlighting(line: int) -> Dictionary: + var colors: Dictionary = {} + var text_edit: TextEdit = get_text_edit() + var text: String = text_edit.get_line(line) + + # Prevents an error from popping up while developing + if not is_instance_valid(text_edit) or text_edit.theme_overrides.is_empty(): + return colors + + # Disable this, as well as the line at the bottom of this function to remove the cache. + if text in cache: + return cache[text] + + # Comments, we have to remove them at this point so the rest of the processing is easier + # Counts both end-of-line and single-line comments + # Comments are not allowed within dialogue lines or response lines, so we ask the parser what it thinks the current line is + if not (dialogue_manager_parser.is_dialogue_line(text) or dialogue_manager_parser.is_response_line(text)) or dialogue_manager_parser.is_line_empty(text) or dialogue_manager_parser.is_import_line(text): + var comment_matches: Array[RegExMatch] = regex_comments.search_all(text) + for comment_match in comment_matches: + for i in ["comment", "comment2"]: + if i in comment_match.names: + colors[comment_match.get_start(i)] = {"color": text_edit.theme_overrides.comments_color} + text = text.substr(0, comment_match.get_start(i)) + + # Dialogues. + var dialogue_matches: Array[RegExMatch] = regex_dialogue.search_all(text) + for dialogue_match in dialogue_matches: + if "random" in dialogue_match.names: + colors[dialogue_match.get_start("random")] = {"color": text_edit.theme_overrides.symbols_color} + colors[dialogue_match.get_end("random")] = {"color": text_edit.theme_overrides.text_color} + if "response" in dialogue_match.names: + colors[dialogue_match.get_start("response")] = {"color": text_edit.theme_overrides.symbols_color} + colors[dialogue_match.get_end("response")] = {"color": text_edit.theme_overrides.text_color} + if "character" in dialogue_match.names: + colors[dialogue_match.get_start("character")] = {"color": text_edit.theme_overrides.members_color} + colors[dialogue_match.get_end("character")] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_dialogue_syntax_highlighting(dialogue_match.get_start("dialogue"), dialogue_match.get_string("dialogue")), true) + + # Title lines. + if dialogue_manager_parser.is_title_line(text): + var title_matches: Array[RegExMatch] = regex_titles.search_all(text) + for title_match in title_matches: + colors[title_match.get_start("title")] = {"color": text_edit.theme_overrides.titles_color} + + # Import lines. + var import_matches: Array[RegExMatch] = dialogue_manager_parser.IMPORT_REGEX.search_all(text) + for import_match in import_matches: + colors[import_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} + colors[import_match.get_start("path") - 1] = {"color": text_edit.theme_overrides.strings_color} + colors[import_match.get_end("path") + 1] = {"color": text_edit.theme_overrides.conditions_color} + colors[import_match.get_start("prefix")] = {"color": text_edit.theme_overrides.members_color} + colors[import_match.get_end("prefix")] = {"color": text_edit.theme_overrides.conditions_color} + + # Using clauses + var using_matches: Array[RegExMatch] = dialogue_manager_parser.USING_REGEX.search_all(text) + for using_match in using_matches: + colors[using_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} + colors[using_match.get_start("state") - 1] = {"color": text_edit.theme_overrides.text_color} + + # Condition keywords and expressions. + var condition_matches: Array[RegExMatch] = regex_condition.search_all(text) + for condition_match in condition_matches: + colors[condition_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} + colors[condition_match.get_end(1)] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_expression_syntax_highlighting(condition_match.get_start("condition"), ExpressionType.IF, condition_match.get_string("condition")), true) + # endif/else + var endcondition_matches: Array[RegExMatch] = regex_endconditions.search_all(text) + for endcondition_match in endcondition_matches: + colors[endcondition_match.get_start(1)] = {"color": text_edit.theme_overrides.conditions_color} + colors[endcondition_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + + # Mutations. + var mutation_matches: Array[RegExMatch] = regex_mutation.search_all(text) + for mutation_match in mutation_matches: + colors[mutation_match.get_start(0)] = {"color": text_edit.theme_overrides.mutations_color} + colors.merge(_get_expression_syntax_highlighting(mutation_match.get_start("mutation"), ExpressionType.DO if mutation_match.strings[1] == "do" else ExpressionType.SET, mutation_match.get_string("mutation")), true) + + # CodeEdit seems to have issues if the Dictionary keys weren't added in order? + var new_colors: Dictionary = {} + var ordered_keys: Array = colors.keys() + ordered_keys.sort() + for index in ordered_keys: + new_colors[index] = colors[index] + + cache[text] = new_colors + return new_colors + + +## Returns the syntax highlighting for a dialogue line +func _get_dialogue_syntax_highlighting(start_index: int, text: String) -> Dictionary: + var text_edit: TextEdit = get_text_edit() + var colors: Dictionary = {} + + # #tag style tags + var hashtag_matches: Array[RegExMatch] = dialogue_manager_parser.TAGS_REGEX.search_all(text) + for hashtag_match in hashtag_matches: + colors[start_index + hashtag_match.get_start(0)] = { "color": text_edit.theme_overrides.comments_color } + colors[start_index + hashtag_match.get_end(0)] = { "color": text_edit.theme_overrides.text_color } + + # Global tags, like bbcode. + var tag_matches: Array[RegExMatch] = regex_tags.search_all(text) + for tag_match in tag_matches: + colors[start_index + tag_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + if "val" in tag_match.names: + colors.merge(_get_literal_syntax_highlighting(start_index + tag_match.get_start("val"), tag_match.get_string("val")), true) + colors[start_index + tag_match.get_end("val")] = {"color": text_edit.theme_overrides.symbols_color} + # Showing the text color straight in the editor for better ease-of-use + if tag_match.get_string("tag") == "color": + colors[start_index + tag_match.get_start("val")] = {"color": Color.from_string(tag_match.get_string("val"), text_edit.theme_overrides.text_color)} + if "text" in tag_match.names: + colors[start_index + tag_match.get_start("text")] = {"color": text_edit.theme_overrides.text_color} + # Text can still contain tags if several effects are applied ([center][b]Something[/b][/center], so recursing + colors.merge(_get_dialogue_syntax_highlighting(start_index + tag_match.get_start("text"), tag_match.get_string("text")), true) + colors[start_index + tag_match.get_end("text")] = {"color": text_edit.theme_overrides.symbols_color} + if "end" in tag_match.names: + colors[start_index + tag_match.get_start("end")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + tag_match.get_end("end")] = {"color": text_edit.theme_overrides.text_color} + colors[start_index + tag_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + # ID tag. + var translation_matches: Array[RegExMatch] = dialogue_manager_parser.TRANSLATION_REGEX.search_all(text) + for translation_match in translation_matches: + colors[start_index + translation_match.get_start(0)] = {"color": text_edit.theme_overrides.comments_color} + colors[start_index + translation_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + # Replacements. + var replacement_matches: Array[RegExMatch] = dialogue_manager_parser.REPLACEMENTS_REGEX.search_all(text) + for replacement_match in replacement_matches: + colors[start_index + replacement_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + replacement_match.get_start(1)] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + replacement_match.get_start(1), replacement_match.strings[1]), true) + colors[start_index + replacement_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + replacement_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + # Jump at the end of a response. + var goto_matches: Array[RegExMatch] = regex_goto.search_all(text) + for goto_match in goto_matches: + colors[start_index + goto_match.get_start(0)] = {"color": text_edit.theme_overrides.jumps_color} + if "file" in goto_match.names: + colors[start_index + goto_match.get_start("file")] = {"color": text_edit.theme_overrides.members_color} + colors[start_index + goto_match.get_end("file")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + goto_match.get_start("title")] = {"color": text_edit.theme_overrides.titles_color} + colors[start_index + goto_match.get_end("title")] = {"color": text_edit.theme_overrides.jumps_color} + colors[start_index + goto_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + # Wrapped condition. + var wcondition_matches: Array[RegExMatch] = regex_wcondition.search_all(text) + for wcondition_match in wcondition_matches: + colors[start_index + wcondition_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + wcondition_match.get_start(0) + 1] = {"color": text_edit.theme_overrides.conditions_color} + colors[start_index + wcondition_match.get_start(0) + 3] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + wcondition_match.get_start("condition"), wcondition_match.get_string("condition")), true) + colors[start_index + wcondition_match.get_end("condition")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + wcondition_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + # [/if] tag for color matching with the opening tag + var wendif_matches: Array[RegExMatch] = regex_wendif.search_all(text) + for wendif_match in wendif_matches: + colors[start_index + wendif_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + wendif_match.get_start(1)] = {"color": text_edit.theme_overrides.conditions_color} + colors[start_index + wendif_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + wendif_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + # Random groups + var rgroup_matches: Array[RegExMatch] = regex_rgroup.search_all(text) + for rgroup_match in rgroup_matches: + colors[start_index + rgroup_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + rgroup_match.get_start("options")] = {"color": text_edit.theme_overrides.text_color} + var separator_matches: Array[RegExMatch] = RegEx.create_from_string("\\|").search_all(rgroup_match.get_string("options")) + for separator_match in separator_matches: + colors[start_index + rgroup_match.get_start("options") + separator_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + rgroup_match.get_start("options") + separator_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + colors[start_index + rgroup_match.get_end("options")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + rgroup_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + return colors + + +## Returns the syntax highlighting for an expression (mutation set/do, or condition) +func _get_expression_syntax_highlighting(start_index: int, type: ExpressionType, text: String) -> Dictionary: + var text_edit: TextEdit = get_text_edit() + var colors: Dictionary = {} + + if type == ExpressionType.SET: + var assignment_matches: Array[RegExMatch] = regex_assignment.search_all(text) + for assignment_match in assignment_matches: + colors[start_index + assignment_match.get_start("var")] = {"color": text_edit.theme_overrides.text_color} + if "attr" in assignment_match.names: + colors[start_index + assignment_match.get_start("attr")] = {"color": text_edit.theme_overrides.members_color} + colors[start_index + assignment_match.get_end("attr")] = {"color": text_edit.theme_overrides.text_color} + if "key" in assignment_match.names: + # Braces are outside of the key, so coloring them symbols_color + colors[start_index + assignment_match.get_start("key") - 1] = {"color": text_edit.theme_overrides.symbols_color} + colors.merge(_get_literal_syntax_highlighting(start_index + assignment_match.get_start("key"), assignment_match.get_string("key")), true) + colors[start_index + assignment_match.get_end("key")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + assignment_match.get_end("key") + 1] = {"color": text_edit.theme_overrides.text_color} + + colors[start_index + assignment_match.get_start("op")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + assignment_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + assignment_match.get_start("val"), assignment_match.get_string("val")), true) + else: + colors.merge(_get_literal_syntax_highlighting(start_index, text), true) + + return colors + + +## Returns the syntax highlighting for a literal. +## For this purpose, "literal" refers to a regular code line that could be used to get a value out of: +## - function calls +## - real literals (bool, string, int, float, etc.) +## - logical operators (>, <, >=, or, and, not, etc.) +func _get_literal_syntax_highlighting(start_index: int, text: String) -> Dictionary: + var text_edit: TextEdit = get_text_edit() + var colors: Dictionary = {} + + # Removing spaces at start/end of the literal + var text_length: int = text.length() + text = text.lstrip(" ") + start_index += text_length - text.length() + text = text.rstrip(" ") + + # Parenthesis expression. + var paren_matches: Array[RegExMatch] = regex_paren.search_all(text) + for paren_match in paren_matches: + colors[start_index + paren_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + paren_match.get_start(0) + 1] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + paren_match.get_start("paren"), paren_match.get_string("paren")), true) + colors[start_index + paren_match.get_end(0) - 1] = {"color": text_edit.theme_overrides.symbols_color} + + # Strings. + var string_matches: Array[RegExMatch] = regex_string.search_all(text) + for string_match in string_matches: + colors[start_index + string_match.get_start(0)] = {"color": text_edit.theme_overrides.strings_color} + if "content" in string_match.names: + var escape_matches: Array[RegExMatch] = regex_escape.search_all(string_match.get_string("content")) + for escape_match in escape_matches: + colors[start_index + string_match.get_start("content") + escape_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + string_match.get_start("content") + escape_match.get_end(0)] = {"color": text_edit.theme_overrides.strings_color} + + # Numbers. + var number_matches: Array[RegExMatch] = regex_number.search_all(text) + for number_match in number_matches: + colors[start_index + number_match.get_start(0)] = {"color": text_edit.theme_overrides.numbers_color} + + # Arrays. + var array_matches: Array[RegExMatch] = regex_array.search_all(text) + for array_match in array_matches: + colors[start_index + array_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors.merge(_get_list_syntax_highlighting(start_index + array_match.get_start(1), array_match.strings[1]), true) + colors[start_index + array_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + + # Dictionaries. + var dict_matches: Array[RegExMatch] = regex_dict.search_all(text) + for dict_match in dict_matches: + colors[start_index + dict_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors.merge(_get_list_syntax_highlighting(start_index + dict_match.get_start(1), dict_match.strings[1]), true) + colors[start_index + dict_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + + # Dictionary key: value pairs + var kvdict_matches: Array[RegExMatch] = regex_kvdict.search_all(text) + for kvdict_match in kvdict_matches: + colors.merge(_get_literal_syntax_highlighting(start_index + kvdict_match.get_start("left"), kvdict_match.get_string("left")), true) + colors[start_index + kvdict_match.get_start("colon")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + kvdict_match.get_end("colon")] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + kvdict_match.get_start("right"), kvdict_match.get_string("right")), true) + + # Booleans. + var bool_matches: Array[RegExMatch] = regex_keyword.search_all(text) + for bool_match in bool_matches: + colors[start_index + bool_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} + + # Functions. + var function_matches: Array[RegExMatch] = regex_function.search_all(text) + for function_match in function_matches: + var last_brace_index: int = text.rfind(")") + colors[start_index + function_match.get_start(1)] = {"color": text_edit.theme_overrides.mutations_color} + colors[start_index + function_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + colors.merge(_get_list_syntax_highlighting(start_index + function_match.get_end(0), text.substr(function_match.get_end(0), last_brace_index - function_match.get_end(0))), true) + colors[start_index + last_brace_index] = {"color": text_edit.theme_overrides.symbols_color} + + # Variables. + var varname_matches: Array[RegExMatch] = regex_varname.search_all(text) + for varname_match in varname_matches: + colors[start_index + varname_match.get_start("var")] = {"color": text_edit.theme_overrides.text_color} + if "attr" in varname_match.names: + colors[start_index + varname_match.get_start("attr")] = {"color": text_edit.theme_overrides.members_color} + colors[start_index + varname_match.get_end("attr")] = {"color": text_edit.theme_overrides.text_color} + if "key" in varname_match.names: + # Braces are outside of the key, so coloring them symbols_color + colors[start_index + varname_match.get_start("key") - 1] = {"color": text_edit.theme_overrides.symbols_color} + colors.merge(_get_literal_syntax_highlighting(start_index + varname_match.get_start("key"), varname_match.get_string("key")), true) + colors[start_index + varname_match.get_end("key")] = {"color": text_edit.theme_overrides.symbols_color} + + # Comparison operators. + var comparison_matches: Array[RegExMatch] = regex_comparison.search_all(text) + for comparison_match in comparison_matches: + colors.merge(_get_literal_syntax_highlighting(start_index + comparison_match.get_start("left"), comparison_match.get_string("left")), true) + colors[start_index + comparison_match.get_start("op")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + comparison_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} + var right = comparison_match.get_string("right") + if right.ends_with(":"): + right = right.substr(0, right.length() - 1) + colors.merge(_get_literal_syntax_highlighting(start_index + comparison_match.get_start("right"), right), true) + colors[start_index + comparison_match.get_start("right") + right.length()] = { "color": text_edit.theme_overrides.symbols_color } + + # Logical binary operators. + var blogical_matches: Array[RegExMatch] = regex_blogical.search_all(text) + for blogical_match in blogical_matches: + colors.merge(_get_literal_syntax_highlighting(start_index + blogical_match.get_start("left"), blogical_match.get_string("left")), true) + colors[start_index + blogical_match.get_start("op")] = {"color": text_edit.theme_overrides.conditions_color} + colors[start_index + blogical_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + blogical_match.get_start("right"), blogical_match.get_string("right")), true) + + # Logical unary operators. + var ulogical_matches: Array[RegExMatch] = regex_ulogical.search_all(text) + for ulogical_match in ulogical_matches: + colors[start_index + ulogical_match.get_start("op")] = {"color": text_edit.theme_overrides.conditions_color} + colors[start_index + ulogical_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + ulogical_match.get_start("right"), ulogical_match.get_string("right")), true) + + return colors + + +## Returns the syntax coloring for a list of literals separated by commas +func _get_list_syntax_highlighting(start_index: int, text: String) -> Dictionary: + var text_edit: TextEdit = get_text_edit() + var colors: Dictionary = {} + + # Comma-separated list of literals (for arrays and function arguments) + var element_matches: Array[RegExMatch] = regex_commas.search_all(text) + for element_match in element_matches: + colors.merge(_get_literal_syntax_highlighting(start_index + element_match.get_start(1), element_match.strings[1]), true) + + return colors diff --git a/addons/dialogue_manager/components/dialogue_cache.gd b/addons/dialogue_manager/components/dialogue_cache.gd new file mode 100644 index 0000000..5304d4b --- /dev/null +++ b/addons/dialogue_manager/components/dialogue_cache.gd @@ -0,0 +1,160 @@ +extends Node + + +const DialogueConstants = preload("../constants.gd") +const DialogueSettings = preload("../settings.gd") +const DialogueManagerParseResult = preload("./parse_result.gd") + + +# Keeps track of errors and dependencies. +# { +# <dialogue file path> = { +# path = <dialogue file path>, +# dependencies = [<dialogue file path>, <dialogue file path>], +# errors = [<error>, <error>] +# } +# } +var _cache: Dictionary = {} + +var _update_dependency_timer: Timer = Timer.new() +var _update_dependency_paths: PackedStringArray = [] + + +func _ready() -> void: + add_child(_update_dependency_timer) + _update_dependency_timer.timeout.connect(_on_update_dependency_timeout) + + _build_cache() + + +func reimport_files(files: PackedStringArray = []) -> void: + if files.is_empty(): files = get_files() + + var file_system: EditorFileSystem = Engine.get_meta("DialogueManagerPlugin") \ + .get_editor_interface() \ + .get_resource_filesystem() + + # NOTE: Godot 4.2rc1 has an issue with reimporting more than one + # file at a time so we do them one by one + for file in files: + file_system.reimport_files([file]) + await get_tree().create_timer(0.2) + + +## Add a dialogue file to the cache. +func add_file(path: String, parse_results: DialogueManagerParseResult = null) -> void: + _cache[path] = { + path = path, + dependencies = [], + errors = [] + } + + if parse_results != null: + _cache[path].dependencies = Array(parse_results.imported_paths).filter(func(d): return d != path) + _cache[path].parsed_at = Time.get_ticks_msec() + + # If this is a fresh cache entry then we need to check for dependencies + if parse_results == null and not _update_dependency_paths.has(path): + queue_updating_dependencies(path) + + +## Get the file paths in the cache. +func get_files() -> PackedStringArray: + return _cache.keys() + + +## Remember any errors in a dialogue file. +func add_errors_to_file(path: String, errors: Array[Dictionary]) -> void: + if _cache.has(path): + _cache[path].errors = errors + else: + _cache[path] = { + path = path, + resource_path = "", + dependencies = [], + errors = errors + } + + +## Get a list of files that have errors in them. +func get_files_with_errors() -> Array[Dictionary]: + var files_with_errors: Array[Dictionary] = [] + for dialogue_file in _cache.values(): + if dialogue_file and dialogue_file.errors.size() > 0: + files_with_errors.append(dialogue_file) + return files_with_errors + + +## Queue a file to have it's dependencies checked +func queue_updating_dependencies(of_path: String) -> void: + _update_dependency_timer.stop() + if not _update_dependency_paths.has(of_path): + _update_dependency_paths.append(of_path) + _update_dependency_timer.start(0.5) + + +## Update any references to a file path that has moved +func move_file_path(from_path: String, to_path: String) -> void: + if not _cache.has(from_path): return + + if to_path != "": + _cache[to_path] = _cache[from_path].duplicate() + _cache.erase(from_path) + + +## Get any dialogue files that import a given path. +func get_files_with_dependency(imported_path: String) -> Array: + return _cache.values().filter(func(d): return d.dependencies.has(imported_path)) + + +## Get any paths that are dependent on a given path +func get_dependent_paths_for_reimport(on_path: String) -> PackedStringArray: + return get_files_with_dependency(on_path) \ + .filter(func(d): return Time.get_ticks_msec() - d.get("parsed_at", 0) > 3000) \ + .map(func(d): return d.path) + + +# Build the initial cache for dialogue files. +func _build_cache() -> void: + var current_files: PackedStringArray = _get_dialogue_files_in_filesystem() + for file in current_files: + add_file(file) + + +# Recursively find any dialogue files in a directory +func _get_dialogue_files_in_filesystem(path: String = "res://") -> PackedStringArray: + var files: PackedStringArray = [] + + if DirAccess.dir_exists_absolute(path): + var dir = DirAccess.open(path) + dir.list_dir_begin() + var file_name = dir.get_next() + while file_name != "": + var file_path: String = (path + "/" + file_name).simplify_path() + if dir.current_is_dir(): + if not file_name in [".godot", ".tmp"]: + files.append_array(_get_dialogue_files_in_filesystem(file_path)) + elif file_name.get_extension() == "dialogue": + files.append(file_path) + file_name = dir.get_next() + + return files + + +### Signals + + +func _on_update_dependency_timeout() -> void: + _update_dependency_timer.stop() + var import_regex: RegEx = RegEx.create_from_string("import \"(?<path>.*?)\"") + var file: FileAccess + var found_imports: Array[RegExMatch] + for path in _update_dependency_paths: + # Open the file and check for any "import" lines + file = FileAccess.open(path, FileAccess.READ) + found_imports = import_regex.search_all(file.get_as_text()) + var dependencies: PackedStringArray = [] + for found in found_imports: + dependencies.append(found.strings[found.names.path]) + _cache[path].dependencies = dependencies + _update_dependency_paths.clear() diff --git a/addons/dialogue_manager/components/download_update_panel.gd b/addons/dialogue_manager/components/download_update_panel.gd new file mode 100644 index 0000000..617d308 --- /dev/null +++ b/addons/dialogue_manager/components/download_update_panel.gd @@ -0,0 +1,84 @@ +@tool +extends Control + + +signal failed() +signal updated(updated_to_version: String) + + +const DialogueConstants = preload("../constants.gd") + +const TEMP_FILE_NAME = "user://temp.zip" + + +@onready var logo: TextureRect = %Logo +@onready var label: Label = $VBox/Label +@onready var http_request: HTTPRequest = $HTTPRequest +@onready var download_button: Button = %DownloadButton + +var next_version_release: Dictionary: + set(value): + next_version_release = value + label.text = DialogueConstants.translate(&"update.is_available_for_download") % value.tag_name.substr(1) + get: + return next_version_release + + +func _ready() -> void: + $VBox/Center/DownloadButton.text = DialogueConstants.translate(&"update.download_update") + $VBox/Center2/NotesButton.text = DialogueConstants.translate(&"update.release_notes") + + +### Signals + + +func _on_download_button_pressed() -> void: + # Safeguard the actual dialogue manager repo from accidentally updating itself + if FileAccess.file_exists("res://examples/test_scenes/test_scene.gd"): + prints("You can't update the addon from within itself.") + failed.emit() + return + + http_request.request(next_version_release.zipball_url) + download_button.disabled = true + download_button.text = DialogueConstants.translate(&"update.downloading") + + +func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void: + if result != HTTPRequest.RESULT_SUCCESS: + failed.emit() + return + + # Save the downloaded zip + var zip_file: FileAccess = FileAccess.open(TEMP_FILE_NAME, FileAccess.WRITE) + zip_file.store_buffer(body) + zip_file.close() + + OS.move_to_trash(ProjectSettings.globalize_path("res://addons/dialogue_manager")) + + var zip_reader: ZIPReader = ZIPReader.new() + zip_reader.open(TEMP_FILE_NAME) + var files: PackedStringArray = zip_reader.get_files() + + var base_path = files[1] + # Remove archive folder + files.remove_at(0) + # Remove assets folder + files.remove_at(0) + + for path in files: + var new_file_path: String = path.replace(base_path, "") + if path.ends_with("/"): + DirAccess.make_dir_recursive_absolute("res://addons/%s" % new_file_path) + else: + var file: FileAccess = FileAccess.open("res://addons/%s" % new_file_path, FileAccess.WRITE) + file.store_buffer(zip_reader.read_file(path)) + + zip_reader.close() + DirAccess.remove_absolute(TEMP_FILE_NAME) + + updated.emit(next_version_release.tag_name.substr(1)) + + +func _on_notes_button_pressed() -> void: + OS.shell_open(next_version_release.html_url) diff --git a/addons/dialogue_manager/components/download_update_panel.tscn b/addons/dialogue_manager/components/download_update_panel.tscn new file mode 100644 index 0000000..f3f4523 --- /dev/null +++ b/addons/dialogue_manager/components/download_update_panel.tscn @@ -0,0 +1,60 @@ +[gd_scene load_steps=3 format=3 uid="uid://qdxrxv3c3hxk"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/download_update_panel.gd" id="1_4tm1k"] +[ext_resource type="Texture2D" uid="uid://d3baj6rygkb3f" path="res://addons/dialogue_manager/assets/update.svg" id="2_4o2m6"] + +[node name="DownloadUpdatePanel" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_4tm1k") + +[node name="HTTPRequest" type="HTTPRequest" parent="."] + +[node name="VBox" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -1.0 +offset_top = 9.0 +offset_right = -1.0 +offset_bottom = 9.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/separation = 10 + +[node name="Logo" type="TextureRect" parent="VBox"] +unique_name_in_owner = true +clip_contents = true +custom_minimum_size = Vector2(300, 80) +layout_mode = 2 +texture = ExtResource("2_4o2m6") +stretch_mode = 5 + +[node name="Label" type="Label" parent="VBox"] +layout_mode = 2 +text = "v1.2.3 is available for download." +horizontal_alignment = 1 + +[node name="Center" type="CenterContainer" parent="VBox"] +layout_mode = 2 + +[node name="DownloadButton" type="Button" parent="VBox/Center"] +unique_name_in_owner = true +layout_mode = 2 +text = "Download update" + +[node name="Center2" type="CenterContainer" parent="VBox"] +layout_mode = 2 + +[node name="NotesButton" type="LinkButton" parent="VBox/Center2"] +layout_mode = 2 +text = "Read release notes" + +[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_request_completed"] +[connection signal="pressed" from="VBox/Center/DownloadButton" to="." method="_on_download_button_pressed"] +[connection signal="pressed" from="VBox/Center2/NotesButton" to="." method="_on_notes_button_pressed"] diff --git a/addons/dialogue_manager/components/errors_panel.gd b/addons/dialogue_manager/components/errors_panel.gd new file mode 100644 index 0000000..f3e294d --- /dev/null +++ b/addons/dialogue_manager/components/errors_panel.gd @@ -0,0 +1,85 @@ +@tool +extends HBoxContainer + + +signal error_pressed(line_number) + + +const DialogueConstants = preload("../constants.gd") + + +@onready var error_button: Button = $ErrorButton +@onready var next_button: Button = $NextButton +@onready var count_label: Label = $CountLabel +@onready var previous_button: Button = $PreviousButton + +## The index of the current error being shown +var error_index: int = 0: + set(next_error_index): + error_index = wrap(next_error_index, 0, errors.size()) + show_error() + get: + return error_index + +## The list of all errors +var errors: Array = []: + set(next_errors): + errors = next_errors + self.error_index = 0 + get: + return errors + + +func _ready() -> void: + apply_theme() + hide() + + +## Set up colors and icons +func apply_theme() -> void: + error_button.add_theme_color_override("font_color", get_theme_color("error_color", "Editor")) + error_button.add_theme_color_override("font_hover_color", get_theme_color("error_color", "Editor")) + error_button.icon = get_theme_icon("StatusError", "EditorIcons") + previous_button.icon = get_theme_icon("ArrowLeft", "EditorIcons") + next_button.icon = get_theme_icon("ArrowRight", "EditorIcons") + + +## Move the error index to match a given line +func show_error_for_line_number(line_number: int) -> void: + for i in range(0, errors.size()): + if errors[i].line_number == line_number: + self.error_index = i + + +## Show the current error +func show_error() -> void: + if errors.size() == 0: + hide() + else: + show() + count_label.text = DialogueConstants.translate(&"n_of_n").format({ index = error_index + 1, total = errors.size() }) + var error = errors[error_index] + error_button.text = DialogueConstants.translate(&"errors.line_and_message").format({ line = error.line_number + 1, column = error.column_number, message = DialogueConstants.get_error_message(error.error) }) + if error.has("external_error"): + error_button.text += " " + DialogueConstants.get_error_message(error.external_error) + + +### Signals + + +func _on_errors_panel_theme_changed() -> void: + apply_theme() + + +func _on_error_button_pressed() -> void: + emit_signal("error_pressed", errors[error_index].line_number, errors[error_index].column_number) + + +func _on_previous_button_pressed() -> void: + self.error_index -= 1 + _on_error_button_pressed() + + +func _on_next_button_pressed() -> void: + self.error_index += 1 + _on_error_button_pressed() diff --git a/addons/dialogue_manager/components/errors_panel.tscn b/addons/dialogue_manager/components/errors_panel.tscn new file mode 100644 index 0000000..956552b --- /dev/null +++ b/addons/dialogue_manager/components/errors_panel.tscn @@ -0,0 +1,56 @@ +[gd_scene load_steps=4 format=3 uid="uid://cs8pwrxr5vxix"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/errors_panel.gd" id="1_nfm3c"] + +[sub_resource type="Image" id="Image_wy5pj"] +data = { +"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), +"format": "RGBA8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id="ImageTexture_s6fxl"] +image = SubResource("Image_wy5pj") + +[node name="ErrorsPanel" type="HBoxContainer"] +visible = false +offset_right = 1024.0 +offset_bottom = 600.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_nfm3c") +metadata/_edit_layout_mode = 1 + +[node name="ErrorButton" type="Button" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_color = Color(0, 0, 0, 1) +theme_override_constants/h_separation = 3 +icon = SubResource("ImageTexture_s6fxl") +flat = true +alignment = 0 +text_overrun_behavior = 4 + +[node name="Spacer" type="Control" parent="."] +custom_minimum_size = Vector2(40, 0) +layout_mode = 2 + +[node name="PreviousButton" type="Button" parent="."] +layout_mode = 2 +icon = SubResource("ImageTexture_s6fxl") +flat = true + +[node name="CountLabel" type="Label" parent="."] +layout_mode = 2 + +[node name="NextButton" type="Button" parent="."] +layout_mode = 2 +icon = SubResource("ImageTexture_s6fxl") +flat = true + +[connection signal="pressed" from="ErrorButton" to="." method="_on_error_button_pressed"] +[connection signal="pressed" from="PreviousButton" to="." method="_on_previous_button_pressed"] +[connection signal="pressed" from="NextButton" to="." method="_on_next_button_pressed"] diff --git a/addons/dialogue_manager/components/files_list.gd b/addons/dialogue_manager/components/files_list.gd new file mode 100644 index 0000000..ac4793d --- /dev/null +++ b/addons/dialogue_manager/components/files_list.gd @@ -0,0 +1,144 @@ +@tool +extends VBoxContainer + + +signal file_selected(file_path: String) +signal file_popup_menu_requested(at_position: Vector2) +signal file_double_clicked(file_path: String) +signal file_middle_clicked(file_path: String) + + +const DialogueConstants = preload("../constants.gd") + +const MODIFIED_SUFFIX = "(*)" + + +@export var icon: Texture2D + +@onready var filter_edit: LineEdit = $FilterEdit +@onready var list: ItemList = $List + +var file_map: Dictionary = {} + +var current_file_path: String = "" + +var files: PackedStringArray = []: + set(next_files): + files = next_files + files.sort() + update_file_map() + apply_filter() + get: + return files + +var unsaved_files: Array[String] = [] + +var filter: String: + set(next_filter): + filter = next_filter + apply_filter() + get: + return filter + + +func _ready() -> void: + apply_theme() + + filter_edit.placeholder_text = DialogueConstants.translate(&"files_list.filter") + + +func select_file(file: String) -> void: + list.deselect_all() + for i in range(0, list.get_item_count()): + var item_text = list.get_item_text(i).replace(MODIFIED_SUFFIX, "") + if item_text == get_nice_file(file, item_text.count("/") + 1): + list.select(i) + + +func mark_file_as_unsaved(file: String, is_unsaved: bool) -> void: + if not file in unsaved_files and is_unsaved: + unsaved_files.append(file) + elif file in unsaved_files and not is_unsaved: + unsaved_files.erase(file) + apply_filter() + + +func update_file_map() -> void: + file_map = {} + for file in files: + var nice_file: String = get_nice_file(file) + + # See if a value with just the file name is already in the map + for key in file_map.keys(): + if file_map[key] == nice_file: + var bit_count = nice_file.count("/") + 2 + + var existing_nice_file = get_nice_file(key, bit_count) + nice_file = get_nice_file(file, bit_count) + + while nice_file == existing_nice_file: + bit_count += 1 + existing_nice_file = get_nice_file(key, bit_count) + nice_file = get_nice_file(file, bit_count) + + file_map[key] = existing_nice_file + + file_map[file] = nice_file + + +func get_nice_file(file_path: String, path_bit_count: int = 1) -> String: + var bits = file_path.replace("res://", "").replace(".dialogue", "").split("/") + bits = bits.slice(-path_bit_count) + return "/".join(bits) + + +func apply_filter() -> void: + list.clear() + for file in file_map.keys(): + if filter == "" or filter.to_lower() in file.to_lower(): + var nice_file = file_map[file] + if file in unsaved_files: + nice_file += MODIFIED_SUFFIX + var new_id := list.add_item(nice_file) + list.set_item_icon(new_id, icon) + + select_file(current_file_path) + + +func apply_theme() -> void: + if is_instance_valid(filter_edit): + filter_edit.right_icon = get_theme_icon("Search", "EditorIcons") + + +### Signals + + +func _on_theme_changed() -> void: + apply_theme() + + +func _on_filter_edit_text_changed(new_text: String) -> void: + self.filter = new_text + + +func _on_list_item_clicked(index: int, at_position: Vector2, mouse_button_index: int) -> void: + if mouse_button_index == MOUSE_BUTTON_LEFT: + var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") + var file = file_map.find_key(item_text) + select_file(file) + file_selected.emit(file) + + if mouse_button_index == MOUSE_BUTTON_RIGHT: + file_popup_menu_requested.emit(at_position) + + if mouse_button_index == MOUSE_BUTTON_MIDDLE: + var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") + var file = file_map.find_key(item_text) + file_middle_clicked.emit(file) + + +func _on_list_item_activated(index: int) -> void: + var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") + var file = file_map.find_key(item_text) + select_file(file) + file_double_clicked.emit(file) diff --git a/addons/dialogue_manager/components/files_list.tscn b/addons/dialogue_manager/components/files_list.tscn new file mode 100644 index 0000000..12bee0b --- /dev/null +++ b/addons/dialogue_manager/components/files_list.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=5 format=3 uid="uid://dnufpcdrreva3"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/files_list.gd" id="1_cytii"] +[ext_resource type="Texture2D" uid="uid://d3lr2uas6ax8v" path="res://addons/dialogue_manager/assets/icon.svg" id="2_3ijx1"] + +[sub_resource type="Image" id="Image_h3jns"] +data = { +"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), +"format": "RGBA8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id="ImageTexture_44sbr"] +image = SubResource("Image_h3jns") + +[node name="FilesList" type="VBoxContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_cytii") +icon = ExtResource("2_3ijx1") + +[node name="FilterEdit" type="LineEdit" parent="."] +layout_mode = 2 +placeholder_text = "Filter files" +clear_button_enabled = true +right_icon = SubResource("ImageTexture_44sbr") + +[node name="List" type="ItemList" parent="."] +layout_mode = 2 +size_flags_vertical = 3 + +[connection signal="theme_changed" from="." to="." method="_on_theme_changed"] +[connection signal="text_changed" from="FilterEdit" to="." method="_on_filter_edit_text_changed"] +[connection signal="item_activated" from="List" to="." method="_on_list_item_activated"] +[connection signal="item_clicked" from="List" to="." method="_on_list_item_clicked"] diff --git a/addons/dialogue_manager/components/find_in_files.gd b/addons/dialogue_manager/components/find_in_files.gd new file mode 100644 index 0000000..916b744 --- /dev/null +++ b/addons/dialogue_manager/components/find_in_files.gd @@ -0,0 +1,229 @@ +@tool +extends Control + +signal result_selected(path: String, cursor: Vector2, length: int) + + +const DialogueConstants = preload("../constants.gd") + + +@export var main_view: Control +@export var code_edit: CodeEdit + +@onready var input: LineEdit = %Input +@onready var search_button: Button = %SearchButton +@onready var match_case_button: CheckBox = %MatchCaseButton +@onready var replace_toggle: CheckButton = %ReplaceToggle +@onready var replace_container: VBoxContainer = %ReplaceContainer +@onready var replace_input: LineEdit = %ReplaceInput +@onready var replace_selected_button: Button = %ReplaceSelectedButton +@onready var replace_all_button: Button = %ReplaceAllButton +@onready var results_container: VBoxContainer = %ResultsContainer +@onready var result_template: HBoxContainer = %ResultTemplate + +var current_results: Dictionary = {}: + set(value): + current_results = value + update_results_view() + if current_results.size() == 0: + replace_selected_button.disabled = true + replace_all_button.disabled = true + else: + replace_selected_button.disabled = false + replace_all_button.disabled = false + get: + return current_results + +var selections: PackedStringArray = [] + + +func prepare() -> void: + input.grab_focus() + + var template_label = result_template.get_node("Label") + template_label.get_theme_stylebox(&"focus").bg_color = code_edit.theme_overrides.current_line_color + template_label.add_theme_font_override(&"normal_font", code_edit.get_theme_font(&"font")) + + replace_toggle.set_pressed_no_signal(false) + replace_container.hide() + + $VBoxContainer/HBoxContainer/FindContainer/Label.text = DialogueConstants.translate(&"search.find") + input.placeholder_text = DialogueConstants.translate(&"search.placeholder") + input.text = "" + search_button.text = DialogueConstants.translate(&"search.find_all") + match_case_button.text = DialogueConstants.translate(&"search.match_case") + replace_toggle.text = DialogueConstants.translate(&"search.toggle_replace") + $VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceLabel.text = DialogueConstants.translate(&"search.replace_with") + replace_input.placeholder_text = DialogueConstants.translate(&"search.replace_placeholder") + replace_input.text = "" + replace_all_button.text = DialogueConstants.translate(&"search.replace_all") + replace_selected_button.text = DialogueConstants.translate(&"search.replace_selected") + + selections.clear() + self.current_results = {} + +#region helpers + + +func update_results_view() -> void: + for child in results_container.get_children(): + child.queue_free() + + for path in current_results.keys(): + var path_label: Label = Label.new() + path_label.text = path + # Show open files + if main_view.open_buffers.has(path): + path_label.text += "(*)" + results_container.add_child(path_label) + for path_result in current_results.get(path): + var result_item: HBoxContainer = result_template.duplicate() + + var checkbox: CheckBox = result_item.get_node("CheckBox") as CheckBox + var key: String = get_selection_key(path, path_result) + checkbox.toggled.connect(func(is_pressed): + if is_pressed: + if not selections.has(key): + selections.append(key) + else: + if selections.has(key): + selections.remove_at(selections.find(key)) + ) + checkbox.set_pressed_no_signal(selections.has(key)) + checkbox.visible = replace_toggle.button_pressed + + var result_label: RichTextLabel = result_item.get_node("Label") as RichTextLabel + var colors: Dictionary = code_edit.theme_overrides + var highlight: String = "" + if replace_toggle.button_pressed: + var matched_word: String = "[bgcolor=" + colors.critical_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + path_result.matched_text + "[/color][/bgcolor]" + highlight = "[s]" + matched_word + "[/s][bgcolor=" + colors.notice_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + replace_input.text + "[/color][/bgcolor]" + else: + highlight = "[bgcolor=" + colors.symbols_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + path_result.matched_text + "[/color][/bgcolor]" + var text: String = path_result.text.substr(0, path_result.index) + highlight + path_result.text.substr(path_result.index + path_result.query.length()) + result_label.text = "%s: %s" % [str(path_result.line).lpad(4), text] + result_label.gui_input.connect(func(event): + if event is InputEventMouseButton and (event as InputEventMouseButton).button_index == MOUSE_BUTTON_LEFT and (event as InputEventMouseButton).double_click: + result_selected.emit(path, Vector2(path_result.index, path_result.line), path_result.query.length()) + ) + + results_container.add_child(result_item) + + +func find_in_files() -> Dictionary: + var results: Dictionary = {} + + var q: String = input.text + var cache = Engine.get_meta("DialogueCache") + var file: FileAccess + for path in cache.get_files(): + var path_results: Array = [] + var lines: PackedStringArray = [] + + if main_view.open_buffers.has(path): + lines = main_view.open_buffers.get(path).text.split("\n") + else: + file = FileAccess.open(path, FileAccess.READ) + lines = file.get_as_text().split("\n") + + for i in range(0, lines.size()): + var index: int = find_in_line(lines[i], q) + while index > -1: + path_results.append({ + line = i, + index = index, + text = lines[i], + matched_text = lines[i].substr(index, q.length()), + query = q + }) + index = find_in_line(lines[i], q, index + q.length()) + + if file != null and file.is_open(): + file.close() + + if path_results.size() > 0: + results[path] = path_results + + return results + + +func get_selection_key(path: String, path_result: Dictionary) -> String: + return "%s-%d-%d" % [path, path_result.line, path_result.index] + + +func find_in_line(line: String, query: String, from_index: int = 0) -> int: + if match_case_button.button_pressed: + return line.find(query, from_index) + else: + return line.findn(query, from_index) + + +func replace_results(only_selected: bool) -> void: + var file: FileAccess + var lines: PackedStringArray = [] + for path in current_results: + if main_view.open_buffers.has(path): + lines = main_view.open_buffers.get(path).text.split("\n") + else: + file = FileAccess.open(path, FileAccess.READ_WRITE) + lines = file.get_as_text().split("\n") + + # Read the results in reverse because we're going to be modifying them as we go + var path_results: Array = current_results.get(path).duplicate() + path_results.reverse() + for path_result in path_results: + var key: String = get_selection_key(path, path_result) + if not only_selected or (only_selected and selections.has(key)): + lines[path_result.line] = lines[path_result.line].substr(0, path_result.index) + replace_input.text + lines[path_result.line].substr(path_result.index + path_result.matched_text.length()) + + var replaced_text: String = "\n".join(lines) + if file != null and file.is_open(): + file.seek(0) + file.store_string(replaced_text) + file.close() + else: + main_view.open_buffers.get(path).text = replaced_text + if main_view.current_file_path == path: + code_edit.text = replaced_text + + current_results = find_in_files() + + +#endregion + +#region signals + + +func _on_search_button_pressed() -> void: + selections.clear() + self.current_results = find_in_files() + + +func _on_input_text_submitted(new_text: String) -> void: + _on_search_button_pressed() + + +func _on_replace_toggle_toggled(toggled_on: bool) -> void: + replace_container.visible = toggled_on + if toggled_on: + replace_input.grab_focus() + update_results_view() + + +func _on_replace_input_text_changed(new_text: String) -> void: + update_results_view() + + +func _on_replace_selected_button_pressed() -> void: + replace_results(true) + + +func _on_replace_all_button_pressed() -> void: + replace_results(false) + + +func _on_match_case_button_toggled(toggled_on: bool) -> void: + _on_search_button_pressed() + + +#endregion diff --git a/addons/dialogue_manager/components/find_in_files.tscn b/addons/dialogue_manager/components/find_in_files.tscn new file mode 100644 index 0000000..8aaef4b --- /dev/null +++ b/addons/dialogue_manager/components/find_in_files.tscn @@ -0,0 +1,139 @@ +[gd_scene load_steps=3 format=3 uid="uid://0n7hwviyyly4"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/find_in_files.gd" id="1_3xicy"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_owohg"] +bg_color = Color(0.266667, 0.278431, 0.352941, 0.243137) +corner_detail = 1 + +[node name="FindInFiles" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("1_3xicy") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="FindContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/FindContainer"] +layout_mode = 2 +text = "Find:" + +[node name="Input" type="LineEdit" parent="VBoxContainer/HBoxContainer/FindContainer"] +unique_name_in_owner = true +layout_mode = 2 +clear_button_enabled = true + +[node name="FindToolbar" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/FindContainer"] +layout_mode = 2 + +[node name="SearchButton" type="Button" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Find all..." + +[node name="MatchCaseButton" type="CheckBox" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Match case" + +[node name="Control" type="Control" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ReplaceToggle" type="CheckButton" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Replace" + +[node name="ReplaceContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ReplaceLabel" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] +layout_mode = 2 +text = "Replace with:" + +[node name="ReplaceInput" type="LineEdit" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +clear_button_enabled = true + +[node name="ReplaceToolbar" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] +layout_mode = 2 + +[node name="ReplaceSelectedButton" type="Button" parent="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Replace selected" + +[node name="ReplaceAllButton" type="Button" parent="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Replace all" + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="ReplaceToolbar" type="HBoxContainer" parent="VBoxContainer/VBoxContainer"] +layout_mode = 2 + +[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +follow_focus = true + +[node name="ResultsContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_constants/separation = 0 + +[node name="ResultTemplate" type="HBoxContainer" parent="."] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 155.0 +offset_top = -74.0 +offset_right = 838.0 +offset_bottom = -51.0 + +[node name="CheckBox" type="CheckBox" parent="ResultTemplate"] +layout_mode = 2 + +[node name="Label" type="RichTextLabel" parent="ResultTemplate"] +layout_mode = 2 +size_flags_horizontal = 3 +focus_mode = 2 +theme_override_styles/focus = SubResource("StyleBoxFlat_owohg") +bbcode_enabled = true +text = "Result" +fit_content = true +scroll_active = false + +[connection signal="text_submitted" from="VBoxContainer/HBoxContainer/FindContainer/Input" to="." method="_on_input_text_submitted"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/SearchButton" to="." method="_on_search_button_pressed"] +[connection signal="toggled" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/MatchCaseButton" to="." method="_on_match_case_button_toggled"] +[connection signal="toggled" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/ReplaceToggle" to="." method="_on_replace_toggle_toggled"] +[connection signal="text_changed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceInput" to="." method="_on_replace_input_text_changed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar/ReplaceSelectedButton" to="." method="_on_replace_selected_button_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar/ReplaceAllButton" to="." method="_on_replace_all_button_pressed"] diff --git a/addons/dialogue_manager/components/parse_result.gd b/addons/dialogue_manager/components/parse_result.gd new file mode 100644 index 0000000..d467cb9 --- /dev/null +++ b/addons/dialogue_manager/components/parse_result.gd @@ -0,0 +1,10 @@ +class_name DialogueManagerParseResult extends RefCounted + +var imported_paths: PackedStringArray = [] +var using_states: PackedStringArray = [] +var titles: Dictionary = {} +var character_names: PackedStringArray = [] +var first_title: String = "" +var lines: Dictionary = {} +var errors: Array[Dictionary] = [] +var raw_text: String = "" diff --git a/addons/dialogue_manager/components/parser.gd b/addons/dialogue_manager/components/parser.gd new file mode 100644 index 0000000..ad6e3ac --- /dev/null +++ b/addons/dialogue_manager/components/parser.gd @@ -0,0 +1,1780 @@ +@tool + +class_name DialogueManagerParser extends Object + + +const DialogueConstants = preload("../constants.gd") +const DialogueSettings = preload("../settings.gd") +const ResolvedLineData = preload("./resolved_line_data.gd") +const ResolvedTagData = preload("./resolved_tag_data.gd") +const DialogueManagerParseResult = preload("./parse_result.gd") + + +var IMPORT_REGEX: RegEx = RegEx.create_from_string("import \"(?<path>[^\"]+)\" as (?<prefix>[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+)") +var USING_REGEX: RegEx = RegEx.create_from_string("using (?<state>.*)") +var VALID_TITLE_REGEX: RegEx = RegEx.create_from_string("^[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+$") +var BEGINS_WITH_NUMBER_REGEX: RegEx = RegEx.create_from_string("^\\d") +var TRANSLATION_REGEX: RegEx = RegEx.create_from_string("\\[ID:(?<tr>.*?)\\]") +var TAGS_REGEX: RegEx = RegEx.create_from_string("\\[#(?<tags>.*?)\\]") +var MUTATION_REGEX: RegEx = RegEx.create_from_string("(?<keyword>do|do!|set) (?<mutation>.*)") +var CONDITION_REGEX: RegEx = RegEx.create_from_string("(if|elif|while|else if) (?<condition>.*)") +var WRAPPED_CONDITION_REGEX: RegEx = RegEx.create_from_string("\\[if (?<condition>.*)\\]") +var REPLACEMENTS_REGEX: RegEx = RegEx.create_from_string("{{(.*?)}}") +var GOTO_REGEX: RegEx = RegEx.create_from_string("=><? (?<jump_to_title>.*)") +var INDENT_REGEX: RegEx = RegEx.create_from_string("^\\t+") +var INLINE_RANDOM_REGEX: RegEx = RegEx.create_from_string("\\[\\[(?<options>.*?)\\]\\]") +var INLINE_CONDITIONALS_REGEX: RegEx = RegEx.create_from_string("\\[if (?<condition>.+?)\\](?<body>.*?)\\[\\/if\\]") + +var TOKEN_DEFINITIONS: Dictionary = { + DialogueConstants.TOKEN_FUNCTION: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*\\("), + DialogueConstants.TOKEN_DICTIONARY_REFERENCE: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*\\["), + DialogueConstants.TOKEN_PARENS_OPEN: RegEx.create_from_string("^\\("), + DialogueConstants.TOKEN_PARENS_CLOSE: RegEx.create_from_string("^\\)"), + DialogueConstants.TOKEN_BRACKET_OPEN: RegEx.create_from_string("^\\["), + DialogueConstants.TOKEN_BRACKET_CLOSE: RegEx.create_from_string("^\\]"), + DialogueConstants.TOKEN_BRACE_OPEN: RegEx.create_from_string("^\\{"), + DialogueConstants.TOKEN_BRACE_CLOSE: RegEx.create_from_string("^\\}"), + DialogueConstants.TOKEN_COLON: RegEx.create_from_string("^:"), + DialogueConstants.TOKEN_COMPARISON: RegEx.create_from_string("^(==|<=|>=|<|>|!=|in )"), + DialogueConstants.TOKEN_ASSIGNMENT: RegEx.create_from_string("^(\\+=|\\-=|\\*=|/=|=)"), + DialogueConstants.TOKEN_NUMBER: RegEx.create_from_string("^\\-?\\d+(\\.\\d+)?"), + DialogueConstants.TOKEN_OPERATOR: RegEx.create_from_string("^(\\+|\\-|\\*|/|%)"), + DialogueConstants.TOKEN_COMMA: RegEx.create_from_string("^,"), + DialogueConstants.TOKEN_DOT: RegEx.create_from_string("^\\."), + DialogueConstants.TOKEN_STRING: RegEx.create_from_string("^(\".*?\"|\'.*?\')"), + DialogueConstants.TOKEN_NOT: RegEx.create_from_string("^(not( |$)|!)"), + DialogueConstants.TOKEN_AND_OR: RegEx.create_from_string("^(and|or)( |$)"), + DialogueConstants.TOKEN_VARIABLE: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*"), + DialogueConstants.TOKEN_COMMENT: RegEx.create_from_string("^#.*"), + DialogueConstants.TOKEN_CONDITION: RegEx.create_from_string("^(if|elif|else)"), + DialogueConstants.TOKEN_BOOL: RegEx.create_from_string("^(true|false)") +} + +var WEIGHTED_RANDOM_SIBLINGS_REGEX: RegEx = RegEx.create_from_string("^\\%(?<weight>[\\d.]+)? ") + +var raw_lines: PackedStringArray = [] +var parent_stack: Array[String] = [] + +var parsed_lines: Dictionary = {} +var imported_paths: PackedStringArray = [] +var using_states: PackedStringArray = [] +var titles: Dictionary = {} +var character_names: PackedStringArray = [] +var first_title: String = "" +var errors: Array[Dictionary] = [] +var raw_text: String = "" + +var _imported_line_map: Dictionary = {} +var _imported_line_count: int = 0 + +var while_loopbacks: Array[String] = [] + + +## Parse some raw dialogue text. Returns a dictionary containing parse results +static func parse_string(string: String, path: String) -> DialogueManagerParseResult: + var parser: DialogueManagerParser = DialogueManagerParser.new() + var error: Error = parser.parse(string, path) + var data: DialogueManagerParseResult = parser.get_data() + parser.free() + + if error == OK: + return data + else: + return null + + +## Extract bbcode and other markers from a string +static func extract_markers_from_string(string: String) -> ResolvedLineData: + var parser: DialogueManagerParser = DialogueManagerParser.new() + var markers: ResolvedLineData = parser.extract_markers(string) + parser.free() + + return markers + + +## Parse some raw dialogue text. Returns a dictionary containing parse results +func parse(text: String, path: String) -> Error: + prepare(text, path) + raw_text = text + + # Parse all of the content + var known_translations = {} + + # Get list of known autoloads + var autoload_names: PackedStringArray = get_autoload_names() + + # Keep track of the last doc comment + var doc_comments: Array[String] = [] + + # Then parse all lines + for id in range(0, raw_lines.size()): + var raw_line: String = raw_lines[id] + + var line: Dictionary = { + id = str(id), + next_id = DialogueConstants.ID_NULL + } + + # Work out if we are inside a conditional or option or if we just + # indented back out of one + var indent_size: int = get_indent(raw_line) + if indent_size < parent_stack.size() and not is_line_empty(raw_line): + for _tab in range(0, parent_stack.size() - indent_size): + parent_stack.pop_back() + + # If we are indented then this line should know about its parent + if parent_stack.size() > 0: + line["parent_id"] = parent_stack.back() + + # Trim any indentation (now that we've calculated it) so we can check + # the begining of each line for its type + raw_line = raw_line.strip_edges(true, false) + + # Grab translations + var translation_key: String = extract_translation(raw_line) + if translation_key != "": + line["translation_key"] = translation_key + raw_line = raw_line.replace("[ID:%s]" % translation_key, "") + + # Check for each kind of line + + # Start shortcuts + if raw_line.begins_with("using "): + var using_match: RegExMatch = USING_REGEX.search(raw_line) + if "state" in using_match.names: + var using_state: String = using_match.strings[using_match.names.state].strip_edges() + if not using_state in autoload_names: + add_error(id, 0, DialogueConstants.ERR_UNKNOWN_USING) + elif not using_state in using_states: + using_states.append(using_state) + continue + + # Response + elif is_response_line(raw_line): + # Add any doc notes + line["notes"] = "\n".join(doc_comments) + doc_comments = [] + + parent_stack.append(str(id)) + line["type"] = DialogueConstants.TYPE_RESPONSE + + # Extract any #tags + var tag_data: ResolvedTagData = extract_tags(raw_line) + line["tags"] = tag_data.tags + raw_line = tag_data.line_without_tags + + if " [if " in raw_line: + line["condition"] = extract_condition(raw_line, true, indent_size) + if " =>" in raw_line: + line["next_id"] = extract_goto(raw_line) + if " =><" in raw_line: + # Because of when the return point needs to be known at runtime we need to split + # this line into two (otherwise the return point would be dependent on the balloon) + var goto_line: Dictionary = { + type = DialogueConstants.TYPE_GOTO, + next_id = extract_goto(raw_line), + next_id_after = find_next_line_after_responses(id), + is_snippet = true + } + parsed_lines[str(id) + ".1"] = goto_line + line["next_id"] = str(id) + ".1" + + # Make sure the added goto line can actually go to somewhere + if goto_line.next_id in [DialogueConstants.ID_ERROR, DialogueConstants.ID_ERROR_INVALID_TITLE, DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY]: + line["next_id"] = goto_line.next_id + + line["character"] = "" + line["character_replacements"] = [] as Array[Dictionary] + line["text"] = extract_response_prompt(raw_line) + + var previous_response_id = find_previous_response_id(id) + if parsed_lines.has(previous_response_id): + var previous_response = parsed_lines[previous_response_id] + # Add this response to the list on the first response so that it is the + # authority on what is in the list of responses + previous_response["responses"] = previous_response["responses"] + PackedStringArray([str(id)]) + else: + # No previous response so this is the first in the list + line["responses"] = PackedStringArray([str(id)]) + + line["next_id_after"] = find_next_line_after_responses(id) + + # If this response has no body then the next id is the next id after + if not line.has("next_id") or line.next_id == DialogueConstants.ID_NULL: + var next_nonempty_line_id = get_next_nonempty_line_id(id) + if next_nonempty_line_id != DialogueConstants.ID_NULL: + if get_indent(raw_lines[next_nonempty_line_id.to_int()]) <= indent_size: + line["next_id"] = line.next_id_after + else: + line["next_id"] = next_nonempty_line_id + + line["text_replacements"] = extract_dialogue_replacements(line.get("text"), indent_size + 2) + for replacement in line.text_replacements: + if replacement.has("error"): + add_error(id, replacement.index, replacement.error) + + # If this response has a character name in it then it will automatically be + # injected as a line of dialogue if the player selects it + var response_text: String = line.text.replace("\\:", "!ESCAPED_COLON!") + if ": " in response_text: + if DialogueSettings.get_setting("create_lines_for_responses_with_characters", true): + var first_child: Dictionary = { + type = DialogueConstants.TYPE_DIALOGUE, + next_id = line.next_id, + next_id_after = line.next_id_after, + text_replacements = line.text_replacements, + tags = line.tags, + translation_key = line.get("translation_key") + } + parse_response_character_and_text(id, response_text, first_child, indent_size, parsed_lines) + line["character"] = first_child.character + line["character_replacements"] = first_child.character_replacements + line["text"] = first_child.text + line["translation_key"] = first_child.translation_key + parsed_lines[str(id) + ".2"] = first_child + line["next_id"] = str(id) + ".2" + else: + parse_response_character_and_text(id, response_text, line, indent_size, parsed_lines) + else: + line["text"] = response_text.replace("!ESCAPED_COLON!", ":") + + # Title + elif is_title_line(raw_line): + line["type"] = DialogueConstants.TYPE_TITLE + if not raw_lines[id].begins_with("~"): + add_error(id, indent_size + 2, DialogueConstants.ERR_NESTED_TITLE) + else: + line["text"] = extract_title(raw_line) + # Titles can't have numbers as the first letter (unless they are external titles which get replaced with hashes) + if id >= _imported_line_count and BEGINS_WITH_NUMBER_REGEX.search(line.text): + add_error(id, 2, DialogueConstants.ERR_TITLE_BEGINS_WITH_NUMBER) + # Only import titles are allowed to have "/" in them + var valid_title = VALID_TITLE_REGEX.search(raw_line.replace("/", "").substr(2).strip_edges()) + if not valid_title: + add_error(id, 2, DialogueConstants.ERR_TITLE_INVALID_CHARACTERS) + + # Condition + elif is_condition_line(raw_line, false): + parent_stack.append(str(id)) + line["type"] = DialogueConstants.TYPE_CONDITION + line["condition"] = extract_condition(raw_line, false, indent_size) + line["next_id_after"] = find_next_line_after_conditions(id) + var next_sibling_id = find_next_condition_sibling(id) + line["next_conditional_id"] = next_sibling_id if is_valid_id(next_sibling_id) else line.next_id_after + + elif is_condition_line(raw_line, true): + parent_stack.append(str(id)) + line["type"] = DialogueConstants.TYPE_CONDITION + line["next_id_after"] = find_next_line_after_conditions(id) + line["next_conditional_id"] = line["next_id_after"] + + elif is_while_condition_line(raw_line): + parent_stack.append(str(id)) + line["type"] = DialogueConstants.TYPE_CONDITION + line["condition"] = extract_condition(raw_line, false, indent_size) + line["next_id_after"] = find_next_line_after_conditions(id) + while_loopbacks.append(find_last_line_within_conditions(id)) + line["next_conditional_id"] = line["next_id_after"] + + # Mutation + elif is_mutation_line(raw_line): + line["type"] = DialogueConstants.TYPE_MUTATION + line["mutation"] = extract_mutation(raw_line) + + # Goto + elif is_goto_line(raw_line): + line["type"] = DialogueConstants.TYPE_GOTO + + if raw_line.begins_with("%"): + apply_weighted_random(id, raw_line, indent_size, line) + + line["next_id"] = extract_goto(raw_line) + if is_goto_snippet_line(raw_line): + line["is_snippet"] = true + line["next_id_after"] = get_line_after_line(id, indent_size, line) + else: + line["is_snippet"] = false + + # Nested dialogue + elif is_nested_dialogue_line(raw_line, parsed_lines, raw_lines, indent_size): + var parent_line: Dictionary = parsed_lines.values().back() + var parent_indent_size: int = get_indent(raw_lines[parent_line.id.to_int()]) + var should_update_translation_key: bool = parent_line.translation_key == parent_line.text + var suffix: String = raw_line.strip_edges(true, false) + if suffix == "": + suffix = " " + parent_line["text"] += "\n" + suffix + parent_line["text_replacements"] = extract_dialogue_replacements(parent_line.text, parent_line.character.length() + 2 + parent_indent_size) + for replacement in parent_line.text_replacements: + if replacement.has("error"): + add_error(id, replacement.index, replacement.error) + + if should_update_translation_key: + parent_line["translation_key"] = parent_line.text + + parent_line["next_id"] = get_line_after_line(id, parent_indent_size, parent_line) + + # Ignore this line when checking for indent errors + remove_error(parent_line.id.to_int(), DialogueConstants.ERR_INVALID_INDENTATION) + + var next_line = raw_lines[parent_line.next_id.to_int()] + if not is_dialogue_line(next_line) and get_indent(next_line) >= indent_size: + add_error(parent_line.next_id.to_int(), indent_size, DialogueConstants.ERR_INVALID_INDENTATION) + + continue + + elif raw_line.strip_edges().begins_with("##"): + doc_comments.append(raw_line.replace("##", "").strip_edges()) + continue + + elif is_line_empty(raw_line) or is_import_line(raw_line): + continue + + # Regular dialogue + else: + # Remove escape character + if raw_line.begins_with("\\using"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\if"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\elif"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\else"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\while"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\-"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\~"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\=>"): raw_line = raw_line.substr(1) + + # Add any doc notes + line["notes"] = "\n".join(doc_comments) + doc_comments = [] + + # Work out any weighted random siblings + if raw_line.begins_with("%"): + apply_weighted_random(id, raw_line, indent_size, line) + raw_line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_line, "") + + line["type"] = DialogueConstants.TYPE_DIALOGUE + + # Extract any tags before we process the line + var tag_data: ResolvedTagData = extract_tags(raw_line) + line["tags"] = tag_data.tags + raw_line = tag_data.line_without_tags + + var l = raw_line.replace("\\:", "!ESCAPED_COLON!") + if ": " in l: + var bits = Array(l.strip_edges().split(": ")) + line["character"] = bits.pop_front().strip_edges() + if not line["character"] in character_names: + character_names.append(line["character"]) + # You can use variables in the character's name + line["character_replacements"] = extract_dialogue_replacements(line.character, indent_size) + for replacement in line.character_replacements: + if replacement.has("error"): + add_error(id, replacement.index, replacement.error) + line["text"] = ": ".join(bits).replace("!ESCAPED_COLON!", ":") + else: + line["character"] = "" + line["character_replacements"] = [] as Array[Dictionary] + line["text"] = l.replace("!ESCAPED_COLON!", ":") + + line["text_replacements"] = extract_dialogue_replacements(line.text, line.character.length() + 2 + indent_size) + for replacement in line.text_replacements: + if replacement.has("error"): + add_error(id, replacement.index, replacement.error) + + # Unescape any newlines + line["text"] = line.text.replace("\\n", "\n").strip_edges() + + # Work out where to go after this line + if line.next_id == DialogueConstants.ID_NULL: + line["next_id"] = get_line_after_line(id, indent_size, line) + + # Check for duplicate translation keys + if line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: + if line.has("translation_key"): + if known_translations.has(line.translation_key) and known_translations.get(line.translation_key) != line.text: + add_error(id, indent_size, DialogueConstants.ERR_DUPLICATE_ID) + else: + known_translations[line.translation_key] = line.text + else: + # Default translations key + if DialogueSettings.get_setting("missing_translations_are_errors", false): + add_error(id, indent_size, DialogueConstants.ERR_MISSING_ID) + else: + line["translation_key"] = line.text + + ## Error checking + + # Can't find goto + var jump_index: int = raw_line.find("=>") + match line.next_id: + DialogueConstants.ID_ERROR: + add_error(id, jump_index, DialogueConstants.ERR_UNKNOWN_TITLE) + DialogueConstants.ID_ERROR_INVALID_TITLE: + add_error(id, jump_index, DialogueConstants.ERR_INVALID_TITLE_REFERENCE) + DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY: + add_error(id, jump_index, DialogueConstants.ERR_TITLE_REFERENCE_HAS_NO_CONTENT) + + # Line after condition isn't indented once to the right + if line.type == DialogueConstants.TYPE_CONDITION: + if is_valid_id(line.next_id): + var next_line: String = raw_lines[line.next_id.to_int()] + var next_indent: int = get_indent(next_line) + if next_indent != indent_size + 1: + add_error(line.next_id.to_int(), next_indent, DialogueConstants.ERR_INVALID_INDENTATION) + else: + add_error(id, indent_size, DialogueConstants.ERR_INVALID_CONDITION_INDENTATION) + + # Line after normal line is indented to the right + elif line.type in [ + DialogueConstants.TYPE_TITLE, + DialogueConstants.TYPE_DIALOGUE, + DialogueConstants.TYPE_MUTATION, + DialogueConstants.TYPE_GOTO + ] and is_valid_id(line.next_id): + var next_line = raw_lines[line.next_id.to_int()] + if next_line != null and get_indent(next_line) > indent_size: + add_error(id, indent_size, DialogueConstants.ERR_INVALID_INDENTATION) + + # Parsing condition failed + if line.has("condition") and line.condition.has("error"): + add_error(id, line.condition.index, line.condition.error) + + # Parsing mutation failed + elif line.has("mutation") and line.mutation.has("error"): + add_error(id, line.mutation.index, line.mutation.error) + + # Line failed to parse at all + if line.get("type") == DialogueConstants.TYPE_UNKNOWN: + add_error(id, 0, DialogueConstants.ERR_UNKNOWN_LINE_SYNTAX) + + # If there are no titles then use the first actual line + if first_title == "" and not is_import_line(raw_line): + first_title = str(id) + + # If this line is the last line of a while loop, edit the id of its next line + if str(id) in while_loopbacks: + if is_goto_snippet_line(raw_line): + line["next_id_after"] = line["parent_id"] + elif is_condition_line(raw_line, true) or is_while_condition_line(raw_line): + line["next_conditional_id"] = line["parent_id"] + line["next_id_after"] = line["parent_id"] + elif is_goto_line(raw_line) or is_title_line(raw_line): + pass + else: + line["next_id"] = line["parent_id"] + + # Done! + parsed_lines[str(id)] = line + + # Assume the last line ends the dialogue + var last_line: Dictionary = parsed_lines.values()[parsed_lines.values().size() - 1] + if last_line.next_id == "": + last_line.next_id = DialogueConstants.ID_END + + if errors.size() > 0: + return ERR_PARSE_ERROR + + return OK + + +func get_data() -> DialogueManagerParseResult: + var data: DialogueManagerParseResult = DialogueManagerParseResult.new() + data.imported_paths = imported_paths + data.using_states = using_states + data.titles = titles + data.character_names = character_names + data.first_title = first_title + data.lines = parsed_lines + data.errors = errors + data.raw_text = raw_text + return data + + +## Get the last parse errors +func get_errors() -> Array[Dictionary]: + return errors + + +## Prepare the parser by collecting all lines and titles +func prepare(text: String, path: String, include_imported_titles_hashes: bool = true) -> void: + using_states = [] + errors = [] + imported_paths = [] + _imported_line_map = {} + while_loopbacks = [] + titles = {} + character_names = [] + first_title = "" + raw_lines = text.split("\n") + + # Work out imports + var known_imports: Dictionary = {} + + # Include the base file path so that we can get around circular dependencies + known_imports[path.hash()] = "." + + var imported_titles: Dictionary = {} + for id in range(0, raw_lines.size()): + var line = raw_lines[id] + if is_import_line(line): + var import_data = extract_import_path_and_name(line) + var import_hash: int = import_data.path.hash() + if import_data.size() > 0: + # Keep track of titles so we can add imported ones later + if str(import_hash) in imported_titles.keys(): + add_error(id, 0, DialogueConstants.ERR_FILE_ALREADY_IMPORTED) + if import_data.prefix in imported_titles.values(): + add_error(id, 0, DialogueConstants.ERR_DUPLICATE_IMPORT_NAME) + imported_titles[str(import_hash)] = import_data.prefix + + # Import the file content + if not known_imports.has(import_hash): + var error: Error = import_content(import_data.path, import_data.prefix, _imported_line_map, known_imports) + if error != OK: + add_error(id, 0, error) + + # Make a map so we can refer compiled lines to where they were imported from + if not _imported_line_map.has(import_hash): + _imported_line_map[import_hash] = { + hash = import_hash, + imported_on_line_number = id, + from_line = 0, + to_line = 0 + } + + var imported_content: String = "" + var cummulative_line_number: int = 0 + for item in _imported_line_map.values(): + item["from_line"] = cummulative_line_number + if known_imports.has(item.hash): + cummulative_line_number += known_imports[item.hash].split("\n").size() + item["to_line"] = cummulative_line_number + if known_imports.has(item.hash): + imported_content += known_imports[item.hash] + "\n" + + _imported_line_count = cummulative_line_number + 1 + + # Join it with the actual content + raw_lines = (imported_content + "\n" + text).split("\n") + + # Find all titles first + for id in range(0, raw_lines.size()): + if raw_lines[id].begins_with("~ "): + var title: String = extract_title(raw_lines[id]) + if title == "": + add_error(id, 2, DialogueConstants.ERR_EMPTY_TITLE) + elif titles.has(title): + add_error(id, 2, DialogueConstants.ERR_DUPLICATE_TITLE) + else: + var next_nonempty_line_id: String = get_next_nonempty_line_id(id) + if next_nonempty_line_id != DialogueConstants.ID_NULL: + titles[title] = next_nonempty_line_id + if "/" in title: + if include_imported_titles_hashes == false: + titles.erase(title) + var bits: PackedStringArray = title.split("/") + if imported_titles.has(bits[0]): + title = imported_titles[bits[0]] + "/" + bits[1] + titles[title] = next_nonempty_line_id + elif first_title == "": + first_title = next_nonempty_line_id + else: + titles[title] = DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY + + +func add_error(line_number: int, column_number: int, error: int) -> void: + # See if the error was in an imported file + for item in _imported_line_map.values(): + if line_number < item.to_line: + errors.append({ + line_number = item.imported_on_line_number, + column_number = 0, + error = DialogueConstants.ERR_ERRORS_IN_IMPORTED_FILE, + external_error = error, + external_line_number = line_number + }) + return + + # Otherwise, it's in this file + errors.append({ + line_number = line_number - _imported_line_count, + column_number = column_number, + error = error + }) + + +func remove_error(line_number: int, error: int) -> void: + for i in range(errors.size() - 1, -1, -1): + var err = errors[i] + var is_native_error = err.line_number == line_number - _imported_line_count and err.error == error + var is_external_error = err.get("external_line_number") == line_number and err.get("external_error") == error + if is_native_error or is_external_error: + errors.remove_at(i) + return + + +func is_import_line(line: String) -> bool: + return line.begins_with("import ") and " as " in line + + +func is_title_line(line: String) -> bool: + return line.strip_edges(true, false).begins_with("~ ") + + +func is_condition_line(line: String, include_else: bool = true) -> bool: + line = line.strip_edges(true, false) + if line.begins_with("if ") or line.begins_with("elif ") or line.begins_with("else if"): return true + if include_else and line.begins_with("else"): return true + return false + +func is_while_condition_line(line: String) -> bool: + line = line.strip_edges(true, false) + if line.begins_with("while "): return true + return false + + +func is_mutation_line(line: String) -> bool: + line = line.strip_edges(true, false) + return line.begins_with("do ") or line.begins_with("do! ") or line.begins_with("set ") + + +func is_goto_line(line: String) -> bool: + line = line.strip_edges(true, false) + line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(line, "") + return line.begins_with("=> ") or line.begins_with("=>< ") + + +func is_goto_snippet_line(line: String) -> bool: + line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(line.strip_edges(), "") + return line.begins_with("=>< ") + + +func is_nested_dialogue_line(raw_line: String, parsed_lines: Dictionary, raw_lines: PackedStringArray, indent_size: int) -> bool: + if parsed_lines.values().is_empty(): return false + if raw_line.strip_edges().begins_with("#"): return false + + var parent_line: Dictionary = parsed_lines.values().back() + if parent_line.type != DialogueConstants.TYPE_DIALOGUE: return false + if get_indent(raw_lines[parent_line.id.to_int()]) >= indent_size: return false + return true + + +func is_dialogue_line(line: String) -> bool: + if line == null: return false + if is_response_line(line): return false + if is_title_line(line): return false + if is_condition_line(line, true): return false + if is_mutation_line(line): return false + if is_goto_line(line): return false + return true + + +func is_response_line(line: String) -> bool: + return line.strip_edges(true, false).begins_with("- ") + + +func is_valid_id(id: String) -> bool: + return false if id in [DialogueConstants.ID_NULL, DialogueConstants.ID_ERROR, DialogueConstants.ID_END_CONVERSATION] else true + + +func is_line_empty(line: String) -> bool: + line = line.strip_edges() + + if line == "": return true + if line == "endif": return true + if line.begins_with("#"): return true + + return false + + +func get_line_after_line(id: int, indent_size: int, line: Dictionary) -> String: + # Unless the next line is an outdent we can assume it comes next + var next_nonempty_line_id = get_next_nonempty_line_id(id) + if next_nonempty_line_id != DialogueConstants.ID_NULL \ + and indent_size <= get_indent(raw_lines[next_nonempty_line_id.to_int()]): + # The next line is a title so we need the next nonempty line after that + if is_title_line(raw_lines[next_nonempty_line_id.to_int()]): + return get_next_nonempty_line_id(next_nonempty_line_id.to_int()) + # Otherwise it's a normal line + else: + return next_nonempty_line_id + # Otherwise, we grab the ID from the parents next ID after children + elif line.has("parent_id") and parsed_lines.has(line.parent_id): + return parsed_lines[line.parent_id].next_id_after + + else: + return DialogueConstants.ID_NULL + + +func get_indent(line: String) -> int: + var tabs: RegExMatch = INDENT_REGEX.search(line) + if tabs: + return tabs.get_string().length() + else: + return 0 + + +func get_next_nonempty_line_id(line_number: int) -> String: + for i in range(line_number + 1, raw_lines.size()): + if not is_line_empty(raw_lines[i]): + return str(i) + return DialogueConstants.ID_NULL + + +func find_previous_response_id(line_number: int) -> String: + var line = raw_lines[line_number] + var indent_size = get_indent(line) + + # Look back up the list to find the previous response + var last_found_response_id: String = str(line_number) + + for i in range(line_number - 1, -1, -1): + line = raw_lines[i] + + if is_line_empty(line): continue + + # If its a response at the same indent level then its a match + elif get_indent(line) == indent_size: + if line.strip_edges().begins_with("- "): + last_found_response_id = str(i) + else: + return last_found_response_id + + # Return itself if nothing was found + return last_found_response_id + + +func apply_weighted_random(id: int, raw_line: String, indent_size: int, line: Dictionary) -> void: + var weight: float = 1 + var found = WEIGHTED_RANDOM_SIBLINGS_REGEX.search(raw_line) + if found and found.names.has("weight"): + weight = found.strings[found.names.weight].to_float() + + # Look back up the list to find the first weighted random line in this group + var original_random_line: Dictionary = {} + for i in range(id, 0, -1): + # Ignore doc comment lines + if raw_lines[i].strip_edges().begins_with("##"): + continue + # Lines that aren't prefixed with the random token are a dead end + if not raw_lines[i].strip_edges().begins_with("%") or get_indent(raw_lines[i]) != indent_size: + break + # Make sure we group random dialogue and random lines separately + elif WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_line.strip_edges(), "").begins_with("=") != WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_lines[i].strip_edges(), "").begins_with("="): + break + # Otherwise we've found the origin + elif parsed_lines.has(str(i)) and parsed_lines[str(i)].has("siblings"): + original_random_line = parsed_lines[str(i)] + break + + # Attach it to the original random line and work out where to go after the line + if original_random_line.size() > 0: + original_random_line["siblings"] += [{ weight = weight, id = str(id) }] + if original_random_line.type != DialogueConstants.TYPE_GOTO: + # Update the next line for all siblings (not goto lines, though, they manager their + # own next ID) + original_random_line["next_id"] = get_line_after_line(id, indent_size, line) + for sibling in original_random_line["siblings"]: + if sibling.id in parsed_lines: + parsed_lines[sibling.id]["next_id"] = original_random_line["next_id"] + line["next_id"] = original_random_line.next_id + # Or set up this line as the original + else: + line["siblings"] = [{ weight = weight, id = str(id) }] + line["next_id"] = get_line_after_line(id, indent_size, line) + + if line.next_id == DialogueConstants.ID_NULL: + line["next_id"] = DialogueConstants.ID_END + + +func find_next_condition_sibling(line_number: int) -> String: + var line = raw_lines[line_number] + var expected_indent = get_indent(line) + + # Look down the list and find an elif or else at the same indent level + for i in range(line_number + 1, raw_lines.size()): + line = raw_lines[i] + if is_line_empty(line): continue + + var l = line.strip_edges() + if l.begins_with("~ "): + return DialogueConstants.ID_END_CONVERSATION + + elif get_indent(line) < expected_indent: + return DialogueConstants.ID_NULL + + elif get_indent(line) == expected_indent: + # Found an if, which begins a different block + if l.begins_with("if"): + return DialogueConstants.ID_NULL + + # Found what we're looking for + elif (l.begins_with("elif ") or l.begins_with("else")): + return str(i) + + return DialogueConstants.ID_NULL + + +func find_next_line_after_conditions(line_number: int) -> String: + var line = raw_lines[line_number] + var expected_indent = get_indent(line) + + # Look down the list for the first non condition line at the same or less indent level + for i in range(line_number + 1, raw_lines.size()): + line = raw_lines[i] + + if is_line_empty(line): continue + + var line_indent = get_indent(line) + line = line.strip_edges() + + if is_title_line(line): + return get_next_nonempty_line_id(i) + + elif line_indent > expected_indent: + continue + + elif line_indent == expected_indent: + if line.begins_with("elif ") or line.begins_with("else"): + continue + else: + return str(i) + + elif line_indent < expected_indent: + # We have to check the parent of this block + for p in range(line_number - 1, -1, -1): + line = raw_lines[p] + + if is_line_empty(line): continue + + line_indent = get_indent(line) + if line_indent < expected_indent: + return parsed_lines[str(p)].get("next_id_after", DialogueConstants.ID_NULL) + + return DialogueConstants.ID_END_CONVERSATION + +func find_last_line_within_conditions(line_number: int) -> String: + var line = raw_lines[line_number] + var expected_indent = get_indent(line) + + var candidate = DialogueConstants.ID_NULL + + # Look down the list for the last line that has an indent level 1 more than this line + # Ending the search when you find a line the same or less indent level + for i in range(line_number + 1, raw_lines.size()): + line = raw_lines[i] + + if is_line_empty(line): continue + + var line_indent = get_indent(line) + line = line.strip_edges() + + if line_indent > expected_indent + 1: + continue + elif line_indent == (expected_indent + 1): + candidate = i + else: + break + + return str(candidate) + +func find_next_line_after_responses(line_number: int) -> String: + var line = raw_lines[line_number] + var expected_indent = get_indent(line) + + # Find the first line after this one that has a smaller indent that isn't another option + # If we hit the eof then we give up + for i in range(line_number + 1, raw_lines.size()): + line = raw_lines[i] + + if is_line_empty(line): continue + + var indent = get_indent(line) + + line = line.strip_edges() + + # We hit a title so the next line is a new start + if is_title_line(line): + return get_next_nonempty_line_id(i) + + # Another option + elif line.begins_with("- "): + if indent == expected_indent: + # ...at the same level so we continue + continue + elif indent < expected_indent: + # ...outdented so check the previous parent + var previous_parent = parent_stack[parent_stack.size() - 2] + if parsed_lines.has(str(previous_parent)): + return parsed_lines[str(previous_parent)].next_id_after + else: + return DialogueConstants.ID_NULL + + # We're at the end of a conditional so jump back up to see what's after it + elif line.begins_with("elif ") or line.begins_with("else"): + for p in range(line_number - 1, -1, -1): + line = raw_lines[p] + + if is_line_empty(line): continue + + var line_indent = get_indent(line) + if line_indent < expected_indent: + return parsed_lines[str(p)].next_id_after + + # Otherwise check the indent for an outdent + else: + line_number = i + line = raw_lines[line_number] + if get_indent(line) <= expected_indent: + return str(line_number) + + # EOF so must be end of conversation + return DialogueConstants.ID_END_CONVERSATION + + +## Get the names of any autoloads in the project +func get_autoload_names() -> PackedStringArray: + var autoloads: PackedStringArray = [] + + var project = ConfigFile.new() + project.load("res://project.godot") + if project.has_section("autoload"): + return Array(project.get_section_keys("autoload")).filter(func(key): return key != "DialogueManager") + + return autoloads + + +## Import content from another dialogue file or return an ERR +func import_content(path: String, prefix: String, imported_line_map: Dictionary, known_imports: Dictionary) -> Error: + if FileAccess.file_exists(path): + var file = FileAccess.open(path, FileAccess.READ) + var content: PackedStringArray = file.get_as_text().split("\n") + + var imported_titles: Dictionary = {} + + for index in range(0, content.size()): + var line = content[index] + if is_import_line(line): + var import = extract_import_path_and_name(line) + if import.size() > 0: + if not known_imports.has(import.path.hash()): + # Add an empty record into the keys just so we don't end up with cyclic dependencies + known_imports[import.path.hash()] = "" + if import_content(import.path, import.prefix, imported_line_map, known_imports) != OK: + return ERR_LINK_FAILED + + if not imported_line_map.has(import.path.hash()): + # Make a map so we can refer compiled lines to where they were imported from + imported_line_map[import.path.hash()] = { + hash = import.path.hash(), + imported_on_line_number = index, + from_line = 0, + to_line = 0 + } + + imported_titles[import.prefix] = import.path.hash() + + var origin_hash: int = -1 + for hash_value in known_imports.keys(): + if known_imports[hash_value] == ".": + origin_hash = hash_value + + # Replace any titles or jump points with references to the files they point to (event if they point to their own file) + for i in range(0, content.size()): + var line = content[i] + if is_title_line(line): + var title = extract_title(line) + if "/" in line: + var bits = title.split("/") + content[i] = "~ %s/%s" % [imported_titles[bits[0]], bits[1]] + else: + content[i] = "~ %s/%s" % [str(path.hash()), title] + + elif "=>< " in line: + var jump: String = line.substr(line.find("=>< ") + "=>< ".length()).strip_edges() + if "/" in jump: + var bits: PackedStringArray = jump.split("/") + var title_hash: int = imported_titles[bits[0]] + if title_hash == origin_hash: + content[i] = "%s=>< %s" % [line.split("=>< ")[0], bits[1]] + else: + content[i] = "%s=>< %s/%s" % [line.split("=>< ")[0], title_hash, bits[1]] + + elif not jump in ["END", "END!"]: + content[i] = "%s=>< %s/%s" % [line.split("=>< ")[0], str(path.hash()), jump] + + elif "=> " in line: + var jump: String = line.substr(line.find("=> ") + "=> ".length()).strip_edges() + if "/" in jump: + var bits: PackedStringArray = jump.split("/") + var title_hash: int = imported_titles[bits[0]] + if title_hash == origin_hash: + content[i] = "%s=> %s" % [line.split("=> ")[0], bits[1]] + else: + content[i] = "%s=> %s/%s" % [line.split("=> ")[0], title_hash, bits[1]] + + elif not jump in ["END", "END!"]: + content[i] = "%s=> %s/%s" % [line.split("=> ")[0], str(path.hash()), jump] + + imported_paths.append(path) + known_imports[path.hash()] = "\n".join(content) + "\n=> END\n" + return OK + else: + return ERR_FILE_NOT_FOUND + + +func extract_import_path_and_name(line: String) -> Dictionary: + var found: RegExMatch = IMPORT_REGEX.search(line) + if found: + return { + path = found.strings[found.names.path], + prefix = found.strings[found.names.prefix] + } + else: + return {} + + +func extract_title(line: String) -> String: + return line.substr(2).strip_edges() + + +func extract_translation(line: String) -> String: + # Find a static translation key, eg. [ID:something] + var found: RegExMatch = TRANSLATION_REGEX.search(line) + if found: + return found.strings[found.names.tr] + else: + return "" + + +func extract_response_prompt(line: String) -> String: + # Find just the text prompt from a response, ignoring any conditions or gotos + line = line.substr(2) + if " [if " in line: + line = line.substr(0, line.find(" [if ")) + if " =>" in line: + line = line.substr(0, line.find(" =>")) + + # Without the translation key if there is one + var translation_key: String = extract_translation(line) + if translation_key: + line = line.replace("[ID:%s]" % translation_key, "") + + return line.replace("\\n", "\n").strip_edges() + + +func parse_response_character_and_text(id: int, text: String, line: Dictionary, indent_size: int, parsed_lines: Dictionary) -> void: + var bits = Array(text.strip_edges().split(": ")) + line["character"] = bits.pop_front().strip_edges() + line["character_replacements"] = extract_dialogue_replacements(line.character, line.character.length() + 2 + indent_size) + for replacement in line.character_replacements: + if replacement.has("error"): + add_error(id, replacement.index, replacement.error) + + if not line["character"] in character_names: + character_names.append(line["character"]) + + line["text"] = ": ".join(bits).replace("!ESCAPED_COLON!", ":").strip_edges() + + if line.get("translation_key", null) == null: + line["translation_key"] = line.text + + +func extract_mutation(line: String) -> Dictionary: + var found: RegExMatch = MUTATION_REGEX.search(line) + + if not found: + return { + index = 0, + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + + if found.names.has("mutation"): + var expression: Array = tokenise(found.strings[found.names.mutation], DialogueConstants.TYPE_MUTATION, found.get_start("mutation")) + if expression.size() == 0: + return { + index = found.get_start("mutation"), + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + elif expression[0].type == DialogueConstants.TYPE_ERROR: + return { + index = expression[0].index, + error = expression[0].value + } + else: + return { + expression = expression, + is_blocking = not "!" in found.strings[found.names.keyword] + } + + else: + return { + index = found.get_start(), + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + + +func extract_condition(raw_line: String, is_wrapped: bool, index: int) -> Dictionary: + var condition: Dictionary = {} + + var regex: RegEx = WRAPPED_CONDITION_REGEX if is_wrapped else CONDITION_REGEX + var found: RegExMatch = regex.search(raw_line) + + if found == null: + return { + index = 0, + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + + var raw_condition: String = found.strings[found.names.condition] + var expression: Array = tokenise(raw_condition, DialogueConstants.TYPE_CONDITION, index + found.get_start("condition")) + + if expression.size() == 0: + return { + index = index + found.get_start("condition"), + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + elif expression[0].type == DialogueConstants.TYPE_ERROR: + return { + index = expression[0].index, + error = expression[0].value + } + else: + return { + expression = expression + } + + +func extract_dialogue_replacements(text: String, index: int) -> Array[Dictionary]: + var founds: Array[RegExMatch] = REPLACEMENTS_REGEX.search_all(text) + + if founds == null or founds.size() == 0: + return [] + + var replacements: Array[Dictionary] = [] + for found in founds: + var replacement: Dictionary = {} + var value_in_text: String = found.strings[1] + var expression: Array = tokenise(value_in_text, DialogueConstants.TYPE_DIALOGUE, index + found.get_start(1)) + if expression.size() == 0: + replacement = { + index = index + found.get_start(1), + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + elif expression[0].type == DialogueConstants.TYPE_ERROR: + replacement = { + index = expression[0].index, + error = expression[0].value + } + else: + replacement = { + value_in_text = "{{%s}}" % value_in_text, + expression = expression + } + replacements.append(replacement) + + return replacements + + +func extract_goto(line: String) -> String: + var found: RegExMatch = GOTO_REGEX.search(line) + + if found == null: return DialogueConstants.ID_ERROR + + var title: String = found.strings[found.names.jump_to_title].strip_edges() + + if " " in title or title == "": + return DialogueConstants.ID_ERROR_INVALID_TITLE + + # "=> END!" means end the conversation + if title == "END!": + return DialogueConstants.ID_END_CONVERSATION + # "=> END" means end the current title (and go back to the previous one if there is one + # in the stack) + elif title == "END": + return DialogueConstants.ID_END + + elif titles.has(title): + return titles.get(title) + else: + return DialogueConstants.ID_ERROR + + +func extract_tags(line: String) -> ResolvedTagData: + var resolved_tags: PackedStringArray = [] + var tag_matches: Array[RegExMatch] = TAGS_REGEX.search_all(line) + for tag_match in tag_matches: + line = line.replace(tag_match.get_string(), "") + var tags = tag_match.get_string().replace("[#", "").replace("]", "").replace(", ", ",").split(",") + for tag in tags: + tag = tag.replace("#", "") + if not tag in resolved_tags: + resolved_tags.append(tag) + + return ResolvedTagData.new({ + tags = resolved_tags, + line_without_tags = line + }) + + +func extract_markers(line: String) -> ResolvedLineData: + var text: String = line + var pauses: Dictionary = {} + var speeds: Dictionary = {} + var mutations: Array[Array] = [] + var bbcodes: Array = [] + var time: String = "" + + # Remove any escaped brackets (ie. "\[") + var escaped_open_brackets: PackedInt32Array = [] + var escaped_close_brackets: PackedInt32Array = [] + for i in range(0, text.length() - 1): + if text.substr(i, 2) == "\\[": + text = text.substr(0, i) + "!" + text.substr(i + 2) + escaped_open_brackets.append(i) + elif text.substr(i, 2) == "\\]": + text = text.substr(0, i) + "!" + text.substr(i + 2) + escaped_close_brackets.append(i) + + # Extract all of the BB codes so that we know the actual text (we could do this easier with + # a RichTextLabel but then we'd need to await idle_frame which is annoying) + var bbcode_positions = find_bbcode_positions_in_string(text) + var accumulaive_length_offset = 0 + for position in bbcode_positions: + # Ignore our own markers + if position.code in ["wait", "speed", "/speed", "do", "do!", "set", "next", "if", "else", "/if"]: + continue + + bbcodes.append({ + bbcode = position.bbcode, + start = position.start, + offset_start = position.start - accumulaive_length_offset + }) + accumulaive_length_offset += position.bbcode.length() + + for bb in bbcodes: + text = text.substr(0, bb.offset_start) + text.substr(bb.offset_start + bb.bbcode.length()) + + # Now find any dialogue markers + var next_bbcode_position = find_bbcode_positions_in_string(text, false) + var limit = 0 + while next_bbcode_position.size() > 0 and limit < 1000: + limit += 1 + + var bbcode = next_bbcode_position[0] + + var index = bbcode.start + var code = bbcode.code + var raw_args = bbcode.raw_args + var args = {} + if code in ["do", "do!", "set"]: + args["value"] = extract_mutation("%s %s" % [code, raw_args]) + else: + # Could be something like: + # "=1.0" + # " rate=20 level=10" + if raw_args and raw_args[0] == "=": + raw_args = "value" + raw_args + for pair in raw_args.strip_edges().split(" "): + if "=" in pair: + var bits = pair.split("=") + args[bits[0]] = bits[1] + + match code: + "wait": + if pauses.has(index): + pauses[index] += args.get("value").to_float() + else: + pauses[index] = args.get("value").to_float() + "speed": + speeds[index] = args.get("value").to_float() + "/speed": + speeds[index] = 1.0 + "do", "do!", "set": + mutations.append([index, args.get("value")]) + "next": + time = args.get("value") if args.has("value") else "0" + + # Find any BB codes that are after this index and remove the length from their start + var length = bbcode.bbcode.length() + for bb in bbcodes: + if bb.offset_start > bbcode.start: + bb.offset_start -= length + bb.start -= length + + # Find any escaped brackets after this that need moving + for i in range(0, escaped_open_brackets.size()): + if escaped_open_brackets[i] > bbcode.start: + escaped_open_brackets[i] -= length + for i in range(0, escaped_close_brackets.size()): + if escaped_close_brackets[i] > bbcode.start: + escaped_close_brackets[i] -= length + + text = text.substr(0, index) + text.substr(index + length) + next_bbcode_position = find_bbcode_positions_in_string(text, false) + + # Put the BB Codes back in + for bb in bbcodes: + text = text.insert(bb.start, bb.bbcode) + + # Put the escaped brackets back in + for index in escaped_open_brackets: + text = text.left(index) + "[" + text.right(text.length() - index - 1) + for index in escaped_close_brackets: + text = text.left(index) + "]" + text.right(text.length() - index - 1) + + return ResolvedLineData.new({ + text = text, + pauses = pauses, + speeds = speeds, + mutations = mutations, + time = time + }) + + +func find_bbcode_positions_in_string(string: String, find_all: bool = true) -> Array[Dictionary]: + if not "[" in string: return [] + + var positions: Array[Dictionary] = [] + + var open_brace_count: int = 0 + var start: int = 0 + var bbcode: String = "" + var code: String = "" + var is_finished_code: bool = false + for i in range(0, string.length()): + if string[i] == "[": + if open_brace_count == 0: + start = i + bbcode = "" + code = "" + is_finished_code = false + open_brace_count += 1 + + else: + if not is_finished_code and (string[i].to_upper() != string[i] or string[i] == "/" or string[i] == "!"): + code += string[i] + else: + is_finished_code = true + + if open_brace_count > 0: + bbcode += string[i] + + if string[i] == "]": + open_brace_count -= 1 + if open_brace_count == 0 and not code in ["if", "else", "/if"]: + positions.append({ + bbcode = bbcode, + code = code, + start = start, + raw_args = bbcode.substr(code.length() + 1, bbcode.length() - code.length() - 2).strip_edges() + }) + + if not find_all: + return positions + + return positions + + +func tokenise(text: String, line_type: String, index: int) -> Array: + var tokens: Array[Dictionary] = [] + var limit: int = 0 + while text.strip_edges() != "" and limit < 1000: + limit += 1 + var found = find_match(text) + if found.size() > 0: + tokens.append({ + index = index, + type = found.type, + value = found.value + }) + index += found.value.length() + text = found.remaining_text + elif text.begins_with(" "): + index += 1 + text = text.substr(1) + else: + return build_token_tree_error(DialogueConstants.ERR_INVALID_EXPRESSION, index) + + return build_token_tree(tokens, line_type, "")[0] + + +func build_token_tree_error(error: int, index: int) -> Array: + return [{ type = DialogueConstants.TOKEN_ERROR, value = error, index = index }] + + +func build_token_tree(tokens: Array[Dictionary], line_type: String, expected_close_token: String) -> Array: + var tree: Array[Dictionary] = [] + var limit = 0 + while tokens.size() > 0 and limit < 1000: + limit += 1 + var token = tokens.pop_front() + + var error = check_next_token(token, tokens, line_type, expected_close_token) + if error != OK: + return [build_token_tree_error(error, token.index), tokens] + + match token.type: + DialogueConstants.TOKEN_FUNCTION: + var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_PARENS_CLOSE) + + if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: + return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] + + tree.append({ + type = DialogueConstants.TOKEN_FUNCTION, + # Consume the trailing "(" + function = token.value.substr(0, token.value.length() - 1), + value = tokens_to_list(sub_tree[0]) + }) + tokens = sub_tree[1] + + DialogueConstants.TOKEN_DICTIONARY_REFERENCE: + var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACKET_CLOSE) + + if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: + return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] + + var args = tokens_to_list(sub_tree[0]) + if args.size() != 1: + return [build_token_tree_error(DialogueConstants.ERR_INVALID_INDEX, token.index), tokens] + + tree.append({ + type = DialogueConstants.TOKEN_DICTIONARY_REFERENCE, + # Consume the trailing "[" + variable = token.value.substr(0, token.value.length() - 1), + value = args[0] + }) + tokens = sub_tree[1] + + DialogueConstants.TOKEN_BRACE_OPEN: + var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACE_CLOSE) + + if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: + return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] + + var t = sub_tree[0] + for i in range(0, t.size() - 2): + # Convert Lua style dictionaries to string keys + if t[i].type == DialogueConstants.TOKEN_VARIABLE and t[i+1].type == DialogueConstants.TOKEN_ASSIGNMENT: + t[i].type = DialogueConstants.TOKEN_STRING + t[i+1].type = DialogueConstants.TOKEN_COLON + t[i+1].erase("value") + + tree.append({ + type = DialogueConstants.TOKEN_DICTIONARY, + value = tokens_to_dictionary(sub_tree[0]) + }) + + tokens = sub_tree[1] + + DialogueConstants.TOKEN_BRACKET_OPEN: + var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACKET_CLOSE) + + if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: + return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] + + var type = DialogueConstants.TOKEN_ARRAY + var value = tokens_to_list(sub_tree[0]) + + # See if this is referencing a nested dictionary value + if tree.size() > 0: + var previous_token = tree[tree.size() - 1] + if previous_token.type in [DialogueConstants.TOKEN_DICTIONARY_REFERENCE, DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE]: + type = DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE + value = value[0] + + tree.append({ + type = type, + value = value + }) + tokens = sub_tree[1] + + DialogueConstants.TOKEN_PARENS_OPEN: + var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_PARENS_CLOSE) + + if sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: + return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] + + tree.append({ + type = DialogueConstants.TOKEN_GROUP, + value = sub_tree[0] + }) + tokens = sub_tree[1] + + DialogueConstants.TOKEN_PARENS_CLOSE, \ + DialogueConstants.TOKEN_BRACE_CLOSE, \ + DialogueConstants.TOKEN_BRACKET_CLOSE: + if token.type != expected_close_token: + return [build_token_tree_error(DialogueConstants.ERR_UNEXPECTED_CLOSING_BRACKET, token.index), tokens] + + return [tree, tokens] + + DialogueConstants.TOKEN_NOT: + # Double nots negate each other + if tokens.size() > 0 and tokens.front().type == DialogueConstants.TOKEN_NOT: + tokens.pop_front() + else: + tree.append({ + type = token.type + }) + + DialogueConstants.TOKEN_COMMA, \ + DialogueConstants.TOKEN_COLON, \ + DialogueConstants.TOKEN_DOT: + tree.append({ + type = token.type + }) + + DialogueConstants.TOKEN_COMPARISON, \ + DialogueConstants.TOKEN_ASSIGNMENT, \ + DialogueConstants.TOKEN_OPERATOR, \ + DialogueConstants.TOKEN_AND_OR, \ + DialogueConstants.TOKEN_VARIABLE: \ + tree.append({ + type = token.type, + value = token.value.strip_edges() + }) + + DialogueConstants.TOKEN_STRING: + tree.append({ + type = token.type, + value = token.value.substr(1, token.value.length() - 2) + }) + + DialogueConstants.TOKEN_CONDITION: + return [build_token_tree_error(DialogueConstants.ERR_UNEXPECTED_CONDITION, token.index), token] + + DialogueConstants.TOKEN_BOOL: + tree.append({ + type = token.type, + value = token.value.to_lower() == "true" + }) + + DialogueConstants.TOKEN_NUMBER: + var value = token.value.to_float() if "." in token.value else token.value.to_int() + # If previous token is a number and this one is a negative number then + # inject a minus operator token in between them. + if tree.size() > 0 and token.value.begins_with("-") and tree[tree.size() - 1].type == DialogueConstants.TOKEN_NUMBER: + tree.append(({ + type = DialogueConstants.TOKEN_OPERATOR, + value = "-" + })) + tree.append({ + type = token.type, + value = -1 * value + }) + else: + tree.append({ + type = token.type, + value = value + }) + + if expected_close_token != "": + var index: int = tokens[0].index if tokens.size() > 0 else 0 + return [build_token_tree_error(DialogueConstants.ERR_MISSING_CLOSING_BRACKET, index), tokens] + + return [tree, tokens] + + +func check_next_token(token: Dictionary, next_tokens: Array[Dictionary], line_type: String, expected_close_token: String) -> Error: + var next_token: Dictionary = { type = null } + if next_tokens.size() > 0: + next_token = next_tokens.front() + + # Guard for assigning in a condition. If the assignment token isn't inside a Lua dictionary + # then it's an unexpected assignment in a condition line. + if token.type == DialogueConstants.TOKEN_ASSIGNMENT and line_type == DialogueConstants.TYPE_CONDITION and not next_tokens.any(func(t): return t.type == expected_close_token): + return DialogueConstants.ERR_UNEXPECTED_ASSIGNMENT + + # Special case for a negative number after this one + if token.type == DialogueConstants.TOKEN_NUMBER and next_token.type == DialogueConstants.TOKEN_NUMBER and next_token.value.begins_with("-"): + return OK + + var expected_token_types = [] + var unexpected_token_types = [] + match token.type: + DialogueConstants.TOKEN_FUNCTION, \ + DialogueConstants.TOKEN_PARENS_OPEN: + unexpected_token_types = [ + null, + DialogueConstants.TOKEN_COMMA, + DialogueConstants.TOKEN_COLON, + DialogueConstants.TOKEN_COMPARISON, + DialogueConstants.TOKEN_ASSIGNMENT, + DialogueConstants.TOKEN_OPERATOR, + DialogueConstants.TOKEN_AND_OR, + DialogueConstants.TOKEN_DOT + ] + + DialogueConstants.TOKEN_BRACKET_CLOSE: + unexpected_token_types = [ + DialogueConstants.TOKEN_NOT, + DialogueConstants.TOKEN_BOOL, + DialogueConstants.TOKEN_STRING, + DialogueConstants.TOKEN_NUMBER, + DialogueConstants.TOKEN_VARIABLE + ] + + DialogueConstants.TOKEN_BRACE_OPEN: + expected_token_types = [ + DialogueConstants.TOKEN_STRING, + DialogueConstants.TOKEN_VARIABLE, + DialogueConstants.TOKEN_NUMBER, + DialogueConstants.TOKEN_BRACE_CLOSE + ] + + DialogueConstants.TOKEN_PARENS_CLOSE, \ + DialogueConstants.TOKEN_BRACE_CLOSE: + unexpected_token_types = [ + DialogueConstants.TOKEN_NOT, + DialogueConstants.TOKEN_ASSIGNMENT, + DialogueConstants.TOKEN_BOOL, + DialogueConstants.TOKEN_STRING, + DialogueConstants.TOKEN_NUMBER, + DialogueConstants.TOKEN_VARIABLE + ] + + DialogueConstants.TOKEN_COMPARISON, \ + DialogueConstants.TOKEN_OPERATOR, \ + DialogueConstants.TOKEN_COMMA, \ + DialogueConstants.TOKEN_DOT, \ + DialogueConstants.TOKEN_NOT, \ + DialogueConstants.TOKEN_AND_OR, \ + DialogueConstants.TOKEN_DICTIONARY_REFERENCE: + unexpected_token_types = [ + null, + DialogueConstants.TOKEN_COMMA, + DialogueConstants.TOKEN_COLON, + DialogueConstants.TOKEN_COMPARISON, + DialogueConstants.TOKEN_ASSIGNMENT, + DialogueConstants.TOKEN_OPERATOR, + DialogueConstants.TOKEN_AND_OR, + DialogueConstants.TOKEN_PARENS_CLOSE, + DialogueConstants.TOKEN_BRACE_CLOSE, + DialogueConstants.TOKEN_BRACKET_CLOSE, + DialogueConstants.TOKEN_DOT + ] + + DialogueConstants.TOKEN_COLON: + unexpected_token_types = [ + DialogueConstants.TOKEN_COMMA, + DialogueConstants.TOKEN_COLON, + DialogueConstants.TOKEN_COMPARISON, + DialogueConstants.TOKEN_ASSIGNMENT, + DialogueConstants.TOKEN_OPERATOR, + DialogueConstants.TOKEN_AND_OR, + DialogueConstants.TOKEN_PARENS_CLOSE, + DialogueConstants.TOKEN_BRACE_CLOSE, + DialogueConstants.TOKEN_BRACKET_CLOSE, + DialogueConstants.TOKEN_DOT + ] + + DialogueConstants.TOKEN_BOOL, \ + DialogueConstants.TOKEN_STRING, \ + DialogueConstants.TOKEN_NUMBER: + unexpected_token_types = [ + DialogueConstants.TOKEN_NOT, + DialogueConstants.TOKEN_ASSIGNMENT, + DialogueConstants.TOKEN_BOOL, + DialogueConstants.TOKEN_STRING, + DialogueConstants.TOKEN_NUMBER, + DialogueConstants.TOKEN_VARIABLE, + DialogueConstants.TOKEN_FUNCTION, + DialogueConstants.TOKEN_PARENS_OPEN, + DialogueConstants.TOKEN_BRACE_OPEN, + DialogueConstants.TOKEN_BRACKET_OPEN + ] + + DialogueConstants.TOKEN_VARIABLE: + unexpected_token_types = [ + DialogueConstants.TOKEN_NOT, + DialogueConstants.TOKEN_BOOL, + DialogueConstants.TOKEN_STRING, + DialogueConstants.TOKEN_NUMBER, + DialogueConstants.TOKEN_VARIABLE, + DialogueConstants.TOKEN_FUNCTION, + DialogueConstants.TOKEN_PARENS_OPEN, + DialogueConstants.TOKEN_BRACE_OPEN, + DialogueConstants.TOKEN_BRACKET_OPEN + ] + + if (expected_token_types.size() > 0 and not next_token.type in expected_token_types or unexpected_token_types.size() > 0 and next_token.type in unexpected_token_types): + match next_token.type: + null: + return DialogueConstants.ERR_UNEXPECTED_END_OF_EXPRESSION + + DialogueConstants.TOKEN_FUNCTION: + return DialogueConstants.ERR_UNEXPECTED_FUNCTION + + DialogueConstants.TOKEN_PARENS_OPEN, \ + DialogueConstants.TOKEN_PARENS_CLOSE: + return DialogueConstants.ERR_UNEXPECTED_BRACKET + + DialogueConstants.TOKEN_COMPARISON, \ + DialogueConstants.TOKEN_ASSIGNMENT, \ + DialogueConstants.TOKEN_OPERATOR, \ + DialogueConstants.TOKEN_NOT, \ + DialogueConstants.TOKEN_AND_OR: + return DialogueConstants.ERR_UNEXPECTED_OPERATOR + + DialogueConstants.TOKEN_COMMA: + return DialogueConstants.ERR_UNEXPECTED_COMMA + DialogueConstants.TOKEN_COLON: + return DialogueConstants.ERR_UNEXPECTED_COLON + DialogueConstants.TOKEN_DOT: + return DialogueConstants.ERR_UNEXPECTED_DOT + + DialogueConstants.TOKEN_BOOL: + return DialogueConstants.ERR_UNEXPECTED_BOOLEAN + DialogueConstants.TOKEN_STRING: + return DialogueConstants.ERR_UNEXPECTED_STRING + DialogueConstants.TOKEN_NUMBER: + return DialogueConstants.ERR_UNEXPECTED_NUMBER + DialogueConstants.TOKEN_VARIABLE: + return DialogueConstants.ERR_UNEXPECTED_VARIABLE + + return DialogueConstants.ERR_INVALID_EXPRESSION + + return OK + + +func tokens_to_list(tokens: Array[Dictionary]) -> Array[Array]: + var list: Array[Array] = [] + var current_item: Array[Dictionary] = [] + for token in tokens: + if token.type == DialogueConstants.TOKEN_COMMA: + list.append(current_item) + current_item = [] + else: + current_item.append(token) + + if current_item.size() > 0: + list.append(current_item) + + return list + + +func tokens_to_dictionary(tokens: Array[Dictionary]) -> Dictionary: + var dictionary = {} + for i in range(0, tokens.size()): + if tokens[i].type == DialogueConstants.TOKEN_COLON: + if tokens.size() == i + 2: + dictionary[tokens[i-1]] = tokens[i+1] + else: + dictionary[tokens[i-1]] = { type = DialogueConstants.TOKEN_GROUP, value = tokens.slice(i+1) } + + return dictionary + + +func find_match(input: String) -> Dictionary: + for key in TOKEN_DEFINITIONS.keys(): + var regex = TOKEN_DEFINITIONS.get(key) + var found = regex.search(input) + if found: + return { + type = key, + remaining_text = input.substr(found.strings[0].length()), + value = found.strings[0] + } + + return {} diff --git a/addons/dialogue_manager/components/resolved_line_data.gd b/addons/dialogue_manager/components/resolved_line_data.gd new file mode 100644 index 0000000..1073586 --- /dev/null +++ b/addons/dialogue_manager/components/resolved_line_data.gd @@ -0,0 +1,15 @@ +extends RefCounted + +var text: String = "" +var pauses: Dictionary = {} +var speeds: Dictionary = {} +var mutations: Array[Array] = [] +var time: String = "" + + +func _init(data: Dictionary) -> void: + text = data.text + pauses = data.pauses + speeds = data.speeds + mutations = data.mutations + time = data.time diff --git a/addons/dialogue_manager/components/resolved_tag_data.gd b/addons/dialogue_manager/components/resolved_tag_data.gd new file mode 100644 index 0000000..728cc42 --- /dev/null +++ b/addons/dialogue_manager/components/resolved_tag_data.gd @@ -0,0 +1,10 @@ +extends RefCounted + + +var tags: PackedStringArray = [] +var line_without_tags: String = "" + + +func _init(data: Dictionary) -> void: + tags = data.tags + line_without_tags = data.line_without_tags diff --git a/addons/dialogue_manager/components/search_and_replace.gd b/addons/dialogue_manager/components/search_and_replace.gd new file mode 100644 index 0000000..c47ac5b --- /dev/null +++ b/addons/dialogue_manager/components/search_and_replace.gd @@ -0,0 +1,210 @@ +@tool +extends VBoxContainer + + +signal open_requested() +signal close_requested() + + +const DialogueConstants = preload("../constants.gd") + + +@onready var input: LineEdit = $Search/Input +@onready var result_label: Label = $Search/ResultLabel +@onready var previous_button: Button = $Search/PreviousButton +@onready var next_button: Button = $Search/NextButton +@onready var match_case_button: CheckBox = $Search/MatchCaseCheckBox +@onready var replace_check_button: CheckButton = $Search/ReplaceCheckButton +@onready var replace_panel: HBoxContainer = $Replace +@onready var replace_input: LineEdit = $Replace/Input +@onready var replace_button: Button = $Replace/ReplaceButton +@onready var replace_all_button: Button = $Replace/ReplaceAllButton + +# The code edit we will be affecting (for some reason exporting this didn't work) +var code_edit: CodeEdit: + set(next_code_edit): + code_edit = next_code_edit + code_edit.gui_input.connect(_on_text_edit_gui_input) + code_edit.text_changed.connect(_on_text_edit_text_changed) + get: + return code_edit + +var results: Array = [] +var result_index: int = -1: + set(next_result_index): + result_index = next_result_index + if results.size() > 0: + var r = results[result_index] + code_edit.set_caret_line(r[0]) + code_edit.select(r[0], r[1], r[0], r[1] + r[2]) + else: + result_index = -1 + if is_instance_valid(code_edit): + code_edit.deselect() + + result_label.text = DialogueConstants.translate(&"n_of_n").format({ index = result_index + 1, total = results.size() }) + get: + return result_index + + +func _ready() -> void: + apply_theme() + + input.placeholder_text = DialogueConstants.translate(&"search.placeholder") + previous_button.tooltip_text = DialogueConstants.translate(&"search.previous") + next_button.tooltip_text = DialogueConstants.translate(&"search.next") + match_case_button.text = DialogueConstants.translate(&"search.match_case") + $Search/ReplaceCheckButton.text = DialogueConstants.translate(&"search.toggle_replace") + replace_button.text = DialogueConstants.translate(&"search.replace") + replace_all_button.text = DialogueConstants.translate(&"search.replace_all") + $Replace/ReplaceLabel.text = DialogueConstants.translate(&"search.replace_with") + + self.result_index = -1 + + replace_panel.hide() + replace_button.disabled = true + replace_all_button.disabled = true + + hide() + + +func focus_line_edit() -> void: + input.grab_focus() + input.select_all() + + +func apply_theme() -> void: + if is_instance_valid(previous_button): + previous_button.icon = get_theme_icon("ArrowLeft", "EditorIcons") + if is_instance_valid(next_button): + next_button.icon = get_theme_icon("ArrowRight", "EditorIcons") + + +# Find text in the code +func search(text: String = "", default_result_index: int = 0) -> void: + results.clear() + + if text == "": + text = input.text + + var lines = code_edit.text.split("\n") + for line_number in range(0, lines.size()): + var line = lines[line_number] + + var column = find_in_line(line, text, 0) + while column > -1: + results.append([line_number, column, text.length()]) + column = find_in_line(line, text, column + 1) + + if results.size() > 0: + replace_button.disabled = false + replace_all_button.disabled = false + else: + replace_button.disabled = true + replace_all_button.disabled = true + + self.result_index = clamp(default_result_index, 0, results.size() - 1) + + +# Find text in a string and match case if requested +func find_in_line(line: String, text: String, from_index: int = 0) -> int: + if match_case_button.button_pressed: + return line.find(text, from_index) + else: + return line.findn(text, from_index) + + +### Signals + + +func _on_text_edit_gui_input(event: InputEvent) -> void: + if event is InputEventKey and event.is_pressed(): + match event.as_text(): + "Ctrl+F", "Command+F": + open_requested.emit() + "Ctrl+Shift+R", "Command+Shift+R": + replace_check_button.set_pressed(true) + open_requested.emit() + + +func _on_text_edit_text_changed() -> void: + results.clear() + + +func _on_search_and_replace_theme_changed() -> void: + apply_theme() + + +func _on_input_text_changed(new_text: String) -> void: + search(new_text) + + +func _on_previous_button_pressed() -> void: + self.result_index = wrapi(result_index - 1, 0, results.size()) + + +func _on_next_button_pressed() -> void: + self.result_index = wrapi(result_index + 1, 0, results.size()) + + +func _on_search_and_replace_visibility_changed() -> void: + if is_instance_valid(input): + if visible: + input.grab_focus() + var selection = code_edit.get_selected_text() + if input.text == "" and selection != "": + input.text = selection + search(selection) + else: + search() + else: + input.text = "" + + +func _on_input_gui_input(event: InputEvent) -> void: + if event is InputEventKey and event.is_pressed(): + match event.as_text(): + "Enter": + search(input.text) + "Escape": + emit_signal("close_requested") + + +func _on_replace_button_pressed() -> void: + if result_index == -1: return + + # Replace the selection at result index + var r: Array = results[result_index] + var lines: PackedStringArray = code_edit.text.split("\n") + var line: String = lines[r[0]] + line = line.substr(0, r[1]) + replace_input.text + line.substr(r[1] + r[2]) + lines[r[0]] = line + code_edit.text = "\n".join(lines) + search(input.text, result_index) + code_edit.text_changed.emit() + + +func _on_replace_all_button_pressed() -> void: + if match_case_button.button_pressed: + code_edit.text = code_edit.text.replace(input.text, replace_input.text) + else: + code_edit.text = code_edit.text.replacen(input.text, replace_input.text) + search() + code_edit.text_changed.emit() + + +func _on_replace_check_button_toggled(button_pressed: bool) -> void: + replace_panel.visible = button_pressed + if button_pressed: + replace_input.grab_focus() + + +func _on_input_focus_entered() -> void: + if results.size() == 0: + search() + else: + self.result_index = result_index + + +func _on_match_case_check_box_toggled(button_pressed: bool) -> void: + search() diff --git a/addons/dialogue_manager/components/search_and_replace.tscn b/addons/dialogue_manager/components/search_and_replace.tscn new file mode 100644 index 0000000..82dd60d --- /dev/null +++ b/addons/dialogue_manager/components/search_and_replace.tscn @@ -0,0 +1,87 @@ +[gd_scene load_steps=2 format=3 uid="uid://gr8nakpbrhby"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/search_and_replace.gd" id="1_8oj1f"] + +[node name="SearchAndReplace" type="VBoxContainer"] +visible = false +anchors_preset = 10 +anchor_right = 1.0 +offset_bottom = 31.0 +grow_horizontal = 2 +size_flags_horizontal = 3 +script = ExtResource("1_8oj1f") + +[node name="Search" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="Input" type="LineEdit" parent="Search"] +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "Text to search for" +metadata/_edit_use_custom_anchors = true + +[node name="MatchCaseCheckBox" type="CheckBox" parent="Search"] +layout_mode = 2 +text = "Match case" + +[node name="VSeparator" type="VSeparator" parent="Search"] +layout_mode = 2 + +[node name="PreviousButton" type="Button" parent="Search"] +layout_mode = 2 +tooltip_text = "Previous" +flat = true + +[node name="ResultLabel" type="Label" parent="Search"] +layout_mode = 2 +text = "0 of 0" + +[node name="NextButton" type="Button" parent="Search"] +layout_mode = 2 +tooltip_text = "Next" +flat = true + +[node name="VSeparator2" type="VSeparator" parent="Search"] +layout_mode = 2 + +[node name="ReplaceCheckButton" type="CheckButton" parent="Search"] +layout_mode = 2 +text = "Replace" + +[node name="Replace" type="HBoxContainer" parent="."] +visible = false +layout_mode = 2 + +[node name="ReplaceLabel" type="Label" parent="Replace"] +layout_mode = 2 +text = "Replace with:" + +[node name="Input" type="LineEdit" parent="Replace"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ReplaceButton" type="Button" parent="Replace"] +layout_mode = 2 +disabled = true +text = "Replace" +flat = true + +[node name="ReplaceAllButton" type="Button" parent="Replace"] +layout_mode = 2 +disabled = true +text = "Replace all" +flat = true + +[connection signal="theme_changed" from="." to="." method="_on_search_and_replace_theme_changed"] +[connection signal="visibility_changed" from="." to="." method="_on_search_and_replace_visibility_changed"] +[connection signal="focus_entered" from="Search/Input" to="." method="_on_input_focus_entered"] +[connection signal="gui_input" from="Search/Input" to="." method="_on_input_gui_input"] +[connection signal="text_changed" from="Search/Input" to="." method="_on_input_text_changed"] +[connection signal="toggled" from="Search/MatchCaseCheckBox" to="." method="_on_match_case_check_box_toggled"] +[connection signal="pressed" from="Search/PreviousButton" to="." method="_on_previous_button_pressed"] +[connection signal="pressed" from="Search/NextButton" to="." method="_on_next_button_pressed"] +[connection signal="toggled" from="Search/ReplaceCheckButton" to="." method="_on_replace_check_button_toggled"] +[connection signal="focus_entered" from="Replace/Input" to="." method="_on_input_focus_entered"] +[connection signal="gui_input" from="Replace/Input" to="." method="_on_input_gui_input"] +[connection signal="pressed" from="Replace/ReplaceButton" to="." method="_on_replace_button_pressed"] +[connection signal="pressed" from="Replace/ReplaceAllButton" to="." method="_on_replace_all_button_pressed"] diff --git a/addons/dialogue_manager/components/title_list.gd b/addons/dialogue_manager/components/title_list.gd new file mode 100644 index 0000000..ee7cd13 --- /dev/null +++ b/addons/dialogue_manager/components/title_list.gd @@ -0,0 +1,67 @@ +@tool +extends VBoxContainer + +signal title_selected(title: String) + + +const DialogueConstants = preload("../constants.gd") + + +@onready var filter_edit: LineEdit = $FilterEdit +@onready var list: ItemList = $List + +var titles: PackedStringArray: + set(next_titles): + titles = next_titles + apply_filter() + get: + return titles + +var filter: String: + set(next_filter): + filter = next_filter + apply_filter() + get: + return filter + + +func _ready() -> void: + apply_theme() + + filter_edit.placeholder_text = DialogueConstants.translate(&"titles_list.filter") + + +func select_title(title: String) -> void: + list.deselect_all() + for i in range(0, list.get_item_count()): + if list.get_item_text(i) == title.strip_edges(): + list.select(i) + + +func apply_filter() -> void: + list.clear() + for title in titles: + if filter == "" or filter.to_lower() in title.to_lower(): + list.add_item(title.strip_edges()) + + +func apply_theme() -> void: + if is_instance_valid(filter_edit): + filter_edit.right_icon = get_theme_icon("Search", "EditorIcons") + + +### Signals + + +func _on_theme_changed() -> void: + apply_theme() + + +func _on_filter_edit_text_changed(new_text: String) -> void: + self.filter = new_text + + +func _on_list_item_clicked(index: int, at_position: Vector2, mouse_button_index: int) -> void: + if mouse_button_index == MOUSE_BUTTON_LEFT: + var title = list.get_item_text(index) + title_selected.emit(title) diff --git a/addons/dialogue_manager/components/title_list.tscn b/addons/dialogue_manager/components/title_list.tscn new file mode 100644 index 0000000..3e5c9a0 --- /dev/null +++ b/addons/dialogue_manager/components/title_list.tscn @@ -0,0 +1,45 @@ +[gd_scene load_steps=4 format=3 uid="uid://ctns6ouwwd68i"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/title_list.gd" id="1_5qqmd"] + +[sub_resource type="Image" id="Image_o5dqs"] +data = { +"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), +"format": "RGBA8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id="ImageTexture_ekmpw"] +image = SubResource("Image_o5dqs") + +[node name="TitleList" type="VBoxContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("1_5qqmd") + +[node name="FilterEdit" type="LineEdit" parent="."] +layout_mode = 2 +offset_right = 1152.0 +offset_bottom = 31.0 +placeholder_text = "Filter titles" +clear_button_enabled = true +right_icon = SubResource("ImageTexture_ekmpw") + +[node name="List" type="ItemList" parent="."] +layout_mode = 2 +offset_top = 35.0 +offset_right = 1152.0 +offset_bottom = 648.0 +size_flags_vertical = 3 +allow_reselect = true + +[connection signal="theme_changed" from="." to="." method="_on_theme_changed"] +[connection signal="text_changed" from="FilterEdit" to="." method="_on_filter_edit_text_changed"] +[connection signal="item_clicked" from="List" to="." method="_on_list_item_clicked"] diff --git a/addons/dialogue_manager/components/update_button.gd b/addons/dialogue_manager/components/update_button.gd new file mode 100644 index 0000000..b8c2809 --- /dev/null +++ b/addons/dialogue_manager/components/update_button.gd @@ -0,0 +1,126 @@ +@tool +extends Button + +const DialogueConstants = preload("../constants.gd") +const DialogueSettings = preload("../settings.gd") + +const REMOTE_RELEASES_URL = "https://api.github.com/repos/nathanhoad/godot_dialogue_manager/releases" + + +@onready var http_request: HTTPRequest = $HTTPRequest +@onready var download_dialog: AcceptDialog = $DownloadDialog +@onready var download_update_panel = $DownloadDialog/DownloadUpdatePanel +@onready var needs_reload_dialog: AcceptDialog = $NeedsReloadDialog +@onready var update_failed_dialog: AcceptDialog = $UpdateFailedDialog +@onready var timer: Timer = $Timer + +# The main editor plugin +var editor_plugin: EditorPlugin + +var needs_reload: bool = false + +# A lambda that gets called just before refreshing the plugin. Return false to stop the reload. +var on_before_refresh: Callable = func(): return true + + +func _ready() -> void: + hide() + apply_theme() + + # Check for updates on GitHub + check_for_update() + + # Check again every few hours + timer.start(60 * 60 * 12) + + +# Convert a version number to an actually comparable number +func version_to_number(version: String) -> int: + var bits = version.split(".") + return bits[0].to_int() * 1000000 + bits[1].to_int() * 1000 + bits[2].to_int() + + +func apply_theme() -> void: + var color: Color = get_theme_color("success_color", "Editor") + + if needs_reload: + color = get_theme_color("error_color", "Editor") + icon = get_theme_icon("Reload", "EditorIcons") + add_theme_color_override("icon_normal_color", color) + add_theme_color_override("icon_focus_color", color) + add_theme_color_override("icon_hover_color", color) + + add_theme_color_override("font_color", color) + add_theme_color_override("font_focus_color", color) + add_theme_color_override("font_hover_color", color) + + +func check_for_update() -> void: + if DialogueSettings.get_user_value("check_for_updates", true): + http_request.request(REMOTE_RELEASES_URL) + + +### Signals + + +func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void: + if result != HTTPRequest.RESULT_SUCCESS: return + + var current_version: String = editor_plugin.get_version() + + # Work out the next version from the releases information on GitHub + var response = JSON.parse_string(body.get_string_from_utf8()) + if typeof(response) != TYPE_ARRAY: return + + # GitHub releases are in order of creation, not order of version + var versions = (response as Array).filter(func(release): + var version: String = release.tag_name.substr(1) + return version_to_number(version) > version_to_number(current_version) + ) + if versions.size() > 0: + download_update_panel.next_version_release = versions[0] + text = DialogueConstants.translate(&"update.available").format({ version = versions[0].tag_name.substr(1) }) + show() + + +func _on_update_button_pressed() -> void: + if needs_reload: + var will_refresh = on_before_refresh.call() + if will_refresh: + editor_plugin.get_editor_interface().restart_editor(true) + else: + var scale: float = editor_plugin.get_editor_interface().get_editor_scale() + download_dialog.min_size = Vector2(300, 250) * scale + download_dialog.popup_centered() + + +func _on_download_dialog_close_requested() -> void: + download_dialog.hide() + + +func _on_download_update_panel_updated(updated_to_version: String) -> void: + download_dialog.hide() + + needs_reload_dialog.dialog_text = DialogueConstants.translate(&"update.needs_reload") + needs_reload_dialog.ok_button_text = DialogueConstants.translate(&"update.reload_ok_button") + needs_reload_dialog.cancel_button_text = DialogueConstants.translate(&"update.reload_cancel_button") + needs_reload_dialog.popup_centered() + + needs_reload = true + text = DialogueConstants.translate(&"update.reload_project") + apply_theme() + + +func _on_download_update_panel_failed() -> void: + download_dialog.hide() + update_failed_dialog.dialog_text = DialogueConstants.translate(&"update.failed") + update_failed_dialog.popup_centered() + + +func _on_needs_reload_dialog_confirmed() -> void: + editor_plugin.get_editor_interface().restart_editor(true) + + +func _on_timer_timeout() -> void: + if not needs_reload: + check_for_update() diff --git a/addons/dialogue_manager/components/update_button.tscn b/addons/dialogue_manager/components/update_button.tscn new file mode 100644 index 0000000..533a94e --- /dev/null +++ b/addons/dialogue_manager/components/update_button.tscn @@ -0,0 +1,42 @@ +[gd_scene load_steps=3 format=3 uid="uid://co8yl23idiwbi"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/update_button.gd" id="1_d2tpb"] +[ext_resource type="PackedScene" uid="uid://qdxrxv3c3hxk" path="res://addons/dialogue_manager/components/download_update_panel.tscn" id="2_iwm7r"] + +[node name="UpdateButton" type="Button"] +visible = false +offset_right = 8.0 +offset_bottom = 8.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_color = Color(0, 0, 0, 1) +theme_override_colors/font_focus_color = Color(0, 0, 0, 1) +text = "v2.9.0 available" +flat = true +script = ExtResource("1_d2tpb") + +[node name="HTTPRequest" type="HTTPRequest" parent="."] + +[node name="DownloadDialog" type="AcceptDialog" parent="."] +title = "Download update" +size = Vector2i(400, 300) +unresizable = true +min_size = Vector2i(300, 250) +ok_button_text = "Close" + +[node name="DownloadUpdatePanel" parent="DownloadDialog" instance=ExtResource("2_iwm7r")] + +[node name="UpdateFailedDialog" type="AcceptDialog" parent="."] +dialog_text = "You have been updated to version 2.4.3" + +[node name="NeedsReloadDialog" type="ConfirmationDialog" parent="."] + +[node name="Timer" type="Timer" parent="."] +wait_time = 14400.0 + +[connection signal="pressed" from="." to="." method="_on_update_button_pressed"] +[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_request_completed"] +[connection signal="close_requested" from="DownloadDialog" to="." method="_on_download_dialog_close_requested"] +[connection signal="failed" from="DownloadDialog/DownloadUpdatePanel" to="." method="_on_download_update_panel_failed"] +[connection signal="updated" from="DownloadDialog/DownloadUpdatePanel" to="." method="_on_download_update_panel_updated"] +[connection signal="confirmed" from="NeedsReloadDialog" to="." method="_on_needs_reload_dialog_confirmed"] +[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"] diff --git a/addons/dialogue_manager/constants.gd b/addons/dialogue_manager/constants.gd new file mode 100644 index 0000000..bc93d21 --- /dev/null +++ b/addons/dialogue_manager/constants.gd @@ -0,0 +1,187 @@ +extends Node + + +const USER_CONFIG_PATH = "user://dialogue_manager_user_config.json" +const CACHE_PATH = "user://dialogue_manager_cache.json" + +# Token types + +const TOKEN_FUNCTION = &"function" +const TOKEN_DICTIONARY_REFERENCE = &"dictionary_reference" +const TOKEN_DICTIONARY_NESTED_REFERENCE = &"dictionary_nested_reference" +const TOKEN_GROUP = &"group" +const TOKEN_ARRAY = &"array" +const TOKEN_DICTIONARY = &"dictionary" +const TOKEN_PARENS_OPEN = &"parens_open" +const TOKEN_PARENS_CLOSE = &"parens_close" +const TOKEN_BRACKET_OPEN = &"bracket_open" +const TOKEN_BRACKET_CLOSE = &"bracket_close" +const TOKEN_BRACE_OPEN = &"brace_open" +const TOKEN_BRACE_CLOSE = &"brace_close" +const TOKEN_COLON = &"colon" +const TOKEN_COMPARISON = &"comparison" +const TOKEN_ASSIGNMENT = &"assignment" +const TOKEN_OPERATOR = &"operator" +const TOKEN_COMMA = &"comma" +const TOKEN_DOT = &"dot" +const TOKEN_CONDITION = &"condition" +const TOKEN_BOOL = &"bool" +const TOKEN_NOT = &"not" +const TOKEN_AND_OR = &"and_or" +const TOKEN_STRING = &"string" +const TOKEN_NUMBER = &"number" +const TOKEN_VARIABLE = &"variable" +const TOKEN_COMMENT = &"comment" + +const TOKEN_ERROR = &"error" + +# Line types + +const TYPE_UNKNOWN = &"unknown" +const TYPE_RESPONSE = &"response" +const TYPE_TITLE = &"title" +const TYPE_CONDITION = &"condition" +const TYPE_MUTATION = &"mutation" +const TYPE_GOTO = &"goto" +const TYPE_DIALOGUE = &"dialogue" +const TYPE_ERROR = &"error" + +const TYPE_ELSE = &"else" + +# Line IDs + +const ID_NULL = &"" +const ID_ERROR = &"error" +const ID_ERROR_INVALID_TITLE = &"invalid title" +const ID_ERROR_TITLE_HAS_NO_BODY = &"title has no body" +const ID_END = &"end" +const ID_END_CONVERSATION = &"end!" + +# Errors + +const ERR_ERRORS_IN_IMPORTED_FILE = 100 +const ERR_FILE_ALREADY_IMPORTED = 101 +const ERR_DUPLICATE_IMPORT_NAME = 102 +const ERR_EMPTY_TITLE = 103 +const ERR_DUPLICATE_TITLE = 104 +const ERR_NESTED_TITLE = 105 +const ERR_TITLE_INVALID_CHARACTERS = 106 +const ERR_UNKNOWN_TITLE = 107 +const ERR_INVALID_TITLE_REFERENCE = 108 +const ERR_TITLE_REFERENCE_HAS_NO_CONTENT = 109 +const ERR_INVALID_EXPRESSION = 110 +const ERR_UNEXPECTED_CONDITION = 111 +const ERR_DUPLICATE_ID = 112 +const ERR_MISSING_ID = 113 +const ERR_INVALID_INDENTATION = 114 +const ERR_INVALID_CONDITION_INDENTATION = 115 +const ERR_INCOMPLETE_EXPRESSION = 116 +const ERR_INVALID_EXPRESSION_FOR_VALUE = 117 +const ERR_UNKNOWN_LINE_SYNTAX = 118 +const ERR_TITLE_BEGINS_WITH_NUMBER = 119 +const ERR_UNEXPECTED_END_OF_EXPRESSION = 120 +const ERR_UNEXPECTED_FUNCTION = 121 +const ERR_UNEXPECTED_BRACKET = 122 +const ERR_UNEXPECTED_CLOSING_BRACKET = 123 +const ERR_MISSING_CLOSING_BRACKET = 124 +const ERR_UNEXPECTED_OPERATOR = 125 +const ERR_UNEXPECTED_COMMA = 126 +const ERR_UNEXPECTED_COLON = 127 +const ERR_UNEXPECTED_DOT = 128 +const ERR_UNEXPECTED_BOOLEAN = 129 +const ERR_UNEXPECTED_STRING = 130 +const ERR_UNEXPECTED_NUMBER = 131 +const ERR_UNEXPECTED_VARIABLE = 132 +const ERR_INVALID_INDEX = 133 +const ERR_UNEXPECTED_ASSIGNMENT = 134 +const ERR_UNKNOWN_USING = 135 + + +## Get the error message +static func get_error_message(error: int) -> String: + match error: + ERR_ERRORS_IN_IMPORTED_FILE: + return translate(&"errors.import_errors") + ERR_FILE_ALREADY_IMPORTED: + return translate(&"errors.already_imported") + ERR_DUPLICATE_IMPORT_NAME: + return translate(&"errors.duplicate_import") + ERR_EMPTY_TITLE: + return translate(&"errors.empty_title") + ERR_DUPLICATE_TITLE: + return translate(&"errors.duplicate_title") + ERR_NESTED_TITLE: + return translate(&"errors.nested_title") + ERR_TITLE_INVALID_CHARACTERS: + return translate(&"errors.invalid_title_string") + ERR_TITLE_BEGINS_WITH_NUMBER: + return translate(&"errors.invalid_title_number") + ERR_UNKNOWN_TITLE: + return translate(&"errors.unknown_title") + ERR_INVALID_TITLE_REFERENCE: + return translate(&"errors.jump_to_invalid_title") + ERR_TITLE_REFERENCE_HAS_NO_CONTENT: + return translate(&"errors.title_has_no_content") + ERR_INVALID_EXPRESSION: + return translate(&"errors.invalid_expression") + ERR_UNEXPECTED_CONDITION: + return translate(&"errors.unexpected_condition") + ERR_DUPLICATE_ID: + return translate(&"errors.duplicate_id") + ERR_MISSING_ID: + return translate(&"errors.missing_id") + ERR_INVALID_INDENTATION: + return translate(&"errors.invalid_indentation") + ERR_INVALID_CONDITION_INDENTATION: + return translate(&"errors.condition_has_no_content") + ERR_INCOMPLETE_EXPRESSION: + return translate(&"errors.incomplete_expression") + ERR_INVALID_EXPRESSION_FOR_VALUE: + return translate(&"errors.invalid_expression_for_value") + ERR_FILE_NOT_FOUND: + return translate(&"errors.file_not_found") + ERR_UNEXPECTED_END_OF_EXPRESSION: + return translate(&"errors.unexpected_end_of_expression") + ERR_UNEXPECTED_FUNCTION: + return translate(&"errors.unexpected_function") + ERR_UNEXPECTED_BRACKET: + return translate(&"errors.unexpected_bracket") + ERR_UNEXPECTED_CLOSING_BRACKET: + return translate(&"errors.unexpected_closing_bracket") + ERR_MISSING_CLOSING_BRACKET: + return translate(&"errors.missing_closing_bracket") + ERR_UNEXPECTED_OPERATOR: + return translate(&"errors.unexpected_operator") + ERR_UNEXPECTED_COMMA: + return translate(&"errors.unexpected_comma") + ERR_UNEXPECTED_COLON: + return translate(&"errors.unexpected_colon") + ERR_UNEXPECTED_DOT: + return translate(&"errors.unexpected_dot") + ERR_UNEXPECTED_BOOLEAN: + return translate(&"errors.unexpected_boolean") + ERR_UNEXPECTED_STRING: + return translate(&"errors.unexpected_string") + ERR_UNEXPECTED_NUMBER: + return translate(&"errors.unexpected_number") + ERR_UNEXPECTED_VARIABLE: + return translate(&"errors.unexpected_variable") + ERR_INVALID_INDEX: + return translate(&"errors.invalid_index") + ERR_UNEXPECTED_ASSIGNMENT: + return translate(&"errors.unexpected_assignment") + ERR_UNKNOWN_USING: + return translate(&"errors.unknown_using") + + return translate(&"errors.unknown") + + +static func translate(string: String) -> String: + var base_path = new().get_script().resource_path.get_base_dir() + + var language: String = TranslationServer.get_tool_locale() + var translations_path: String = "%s/l10n/%s.po" % [base_path, language] + var fallback_translations_path: String = "%s/l10n/%s.po" % [base_path, TranslationServer.get_tool_locale().substr(0, 2)] + var en_translations_path: String = "%s/l10n/en.po" % base_path + var translations: Translation = load(translations_path if FileAccess.file_exists(translations_path) else (fallback_translations_path if FileAccess.file_exists(fallback_translations_path) else en_translations_path)) + return translations.get_message(string) diff --git a/addons/dialogue_manager/dialogue_label.gd b/addons/dialogue_manager/dialogue_label.gd new file mode 100644 index 0000000..24057be --- /dev/null +++ b/addons/dialogue_manager/dialogue_label.gd @@ -0,0 +1,226 @@ +@icon("./assets/icon.svg") + +@tool + +## A RichTextLabel specifically for use with [b]Dialogue Manager[/b] dialogue. +class_name DialogueLabel extends RichTextLabel + + +## Emitted for each letter typed out. +signal spoke(letter: String, letter_index: int, speed: float) + +## Emitted when typing paused for a `[wait]` +signal paused_typing(duration: float) + +## Emitted when the player skips the typing of dialogue. +signal skipped_typing() + +## Emitted when typing finishes. +signal finished_typing() + + +# The action to press to skip typing. +@export var skip_action: StringName = &"ui_cancel" + +## The speed with which the text types out. +@export var seconds_per_step: float = 0.02 + +## Automatically have a brief pause when these characters are encountered. +@export var pause_at_characters: String = ".?!" + +## Don't auto pause if the charcter after the pause is one of these. +@export var skip_pause_at_character_if_followed_by: String = ")\"" + +## Don't auto pause after these abbreviations (only if "." is in `pause_at_characters`).[br] +## Abbreviations are limitted to 5 characters in length [br] +## Does not support multi-period abbreviations (ex. "p.m.") +@export var skip_pause_at_abbreviations: PackedStringArray = ["Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex"] + +## The amount of time to pause when exposing a character present in pause_at_characters. +@export var seconds_per_pause_step: float = 0.3 + + +## The current line of dialogue. +var dialogue_line: + set(next_dialogue_line): + dialogue_line = next_dialogue_line + custom_minimum_size = Vector2.ZERO + text = dialogue_line.text + get: + return dialogue_line + +## Whether the label is currently typing itself out. +var is_typing: bool = false: + set(value): + var is_finished: bool = is_typing != value and value == false + is_typing = value + if is_finished: + finished_typing.emit() + get: + return is_typing + +var _last_wait_index: int = -1 +var _last_mutation_index: int = -1 +var _waiting_seconds: float = 0 +var _is_awaiting_mutation: bool = false + + +func _process(delta: float) -> void: + if self.is_typing: + # Type out text + if visible_ratio < 1: + # See if we are waiting + if _waiting_seconds > 0: + _waiting_seconds = _waiting_seconds - delta + # If we are no longer waiting then keep typing + if _waiting_seconds <= 0: + _type_next(delta, _waiting_seconds) + else: + # Make sure any mutations at the end of the line get run + _mutate_inline_mutations(get_total_character_count()) + self.is_typing = false + + +func _unhandled_input(event: InputEvent) -> void: + # Note: this will no longer be reached if using Dialogue Manager > 2.32.2. To make skip handling + # simpler (so all of mouse/keyboard/joypad are together) it is now the responsibility of the + # dialogue balloon. + if self.is_typing and visible_ratio < 1 and InputMap.has_action(skip_action) and event.is_action_pressed(skip_action): + get_viewport().set_input_as_handled() + skip_typing() + + +## Start typing out the text +func type_out() -> void: + text = dialogue_line.text + visible_characters = 0 + visible_ratio = 0 + _waiting_seconds = 0 + _last_wait_index = -1 + _last_mutation_index = -1 + + self.is_typing = true + + # Allow typing listeners a chance to connect + await get_tree().process_frame + + if get_total_character_count() == 0: + self.is_typing = false + elif seconds_per_step == 0: + _mutate_remaining_mutations() + visible_characters = get_total_character_count() + self.is_typing = false + + +## Stop typing out the text and jump right to the end +func skip_typing() -> void: + _mutate_remaining_mutations() + visible_characters = get_total_character_count() + self.is_typing = false + skipped_typing.emit() + + +# Type out the next character(s) +func _type_next(delta: float, seconds_needed: float) -> void: + if _is_awaiting_mutation: return + + if visible_characters == get_total_character_count(): + return + + if _last_mutation_index != visible_characters: + _last_mutation_index = visible_characters + _mutate_inline_mutations(visible_characters) + if _is_awaiting_mutation: return + + var additional_waiting_seconds: float = _get_pause(visible_characters) + + # Pause on characters like "." + if _should_auto_pause(): + additional_waiting_seconds += seconds_per_pause_step + + # Pause at literal [wait] directives + if _last_wait_index != visible_characters and additional_waiting_seconds > 0: + _last_wait_index = visible_characters + _waiting_seconds += additional_waiting_seconds + paused_typing.emit(_get_pause(visible_characters)) + else: + visible_characters += 1 + if visible_characters <= get_total_character_count(): + spoke.emit(get_parsed_text()[visible_characters - 1], visible_characters - 1, _get_speed(visible_characters)) + # See if there's time to type out some more in this frame + seconds_needed += seconds_per_step * (1.0 / _get_speed(visible_characters)) + if seconds_needed > delta: + _waiting_seconds += seconds_needed + else: + _type_next(delta, seconds_needed) + + +# Get the pause for the current typing position if there is one +func _get_pause(at_index: int) -> float: + return dialogue_line.pauses.get(at_index, 0) + + +# Get the speed for the current typing position +func _get_speed(at_index: int) -> float: + var speed: float = 1 + for index in dialogue_line.speeds: + if index > at_index: + return speed + speed = dialogue_line.speeds[index] + return speed + + +# Run any inline mutations that haven't been run yet +func _mutate_remaining_mutations() -> void: + for i in range(visible_characters, get_total_character_count() + 1): + _mutate_inline_mutations(i) + + +# Run any mutations at the current typing position +func _mutate_inline_mutations(index: int) -> void: + for inline_mutation in dialogue_line.inline_mutations: + # inline mutations are an array of arrays in the form of [character index, resolvable function] + if inline_mutation[0] > index: + return + if inline_mutation[0] == index: + _is_awaiting_mutation = true + # The DialogueManager can't be referenced directly here so we need to get it by its path + await Engine.get_singleton("DialogueManager").mutate(inline_mutation[1], dialogue_line.extra_game_states, true) + _is_awaiting_mutation = false + + +# Determine if the current autopause character at the cursor should qualify to pause typing. +func _should_auto_pause() -> bool: + if visible_characters == 0: return false + + var parsed_text: String = get_parsed_text() + + # Avoid outofbounds when the label auto-translates and the text changes to one shorter while typing out + # Note: visible characters can be larger than parsed_text after a translation event + if visible_characters >= parsed_text.length(): return false + + # Ignore pause characters if they are next to a non-pause character + if parsed_text[visible_characters] in skip_pause_at_character_if_followed_by.split(): + return false + + # Ignore "." if it's between two numbers + if visible_characters > 3 and parsed_text[visible_characters - 1] == ".": + var possible_number: String = parsed_text.substr(visible_characters - 2, 3) + if str(float(possible_number)) == possible_number: + return false + + # Ignore "." if it's used in an abbreviation + # Note: does NOT support multi-period abbreviations (ex. p.m.) + if "." in pause_at_characters and parsed_text[visible_characters - 1] == ".": + for abbreviation in skip_pause_at_abbreviations: + if visible_characters >= abbreviation.length(): + var previous_characters: String = parsed_text.substr(visible_characters - abbreviation.length() - 1, abbreviation.length()) + if previous_characters == abbreviation: + return false + + # Ignore two non-"." characters next to each other + var other_pause_characters: PackedStringArray = pause_at_characters.replace(".", "").split() + if visible_characters > 1 and parsed_text[visible_characters - 1] in other_pause_characters and parsed_text[visible_characters] in other_pause_characters: + return false + + return parsed_text[visible_characters - 1] in pause_at_characters.split() diff --git a/addons/dialogue_manager/dialogue_label.tscn b/addons/dialogue_manager/dialogue_label.tscn new file mode 100644 index 0000000..df48b64 --- /dev/null +++ b/addons/dialogue_manager/dialogue_label.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=2 format=3 uid="uid://ckvgyvclnwggo"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_label.gd" id="1_cital"] + +[node name="DialogueLabel" type="RichTextLabel"] +anchors_preset = 10 +anchor_right = 1.0 +grow_horizontal = 2 +mouse_filter = 1 +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 = 1 +script = ExtResource("1_cital") +skip_pause_at_abbreviations = PackedStringArray("Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex") diff --git a/addons/dialogue_manager/dialogue_line.gd b/addons/dialogue_manager/dialogue_line.gd new file mode 100644 index 0000000..a9bf84a --- /dev/null +++ b/addons/dialogue_manager/dialogue_line.gd @@ -0,0 +1,98 @@ +## A line of dialogue returned from [code]DialogueManager[/code]. +class_name DialogueLine extends RefCounted + + +const _DialogueConstants = preload("./constants.gd") + + +## The ID of this line +var id: String + +## The internal type of this dialogue object. One of [code]TYPE_DIALOGUE[/code] or [code]TYPE_MUTATION[/code] +var type: String = _DialogueConstants.TYPE_DIALOGUE + +## The next line ID after this line. +var next_id: String = "" + +## The character name that is saying this line. +var character: String = "" + +## A dictionary of variable replacements fo the character name. Generally for internal use only. +var character_replacements: Array[Dictionary] = [] + +## The dialogue being spoken. +var text: String = "" + +## A dictionary of replacements for the text. Generally for internal use only. +var text_replacements: Array[Dictionary] = [] + +## The key to use for translating this line. +var translation_key: String = "" + +## A map for when and for how long to pause while typing out the dialogue text. +var pauses: Dictionary = {} + +## A map for speed changes when typing out the dialogue text. +var speeds: Dictionary = {} + +## A map of any mutations to run while typing out the dialogue text. +var inline_mutations: Array[Array] = [] + +## A list of responses attached to this line of dialogue. +var responses: Array[DialogueResponse] = [] + +## A list of any extra game states to check when resolving variables and mutations. +var extra_game_states: Array = [] + +## How long to show this line before advancing to the next. Either a float (of seconds), [code]"auto"[/code], or [code]null[/code]. +var time: String = "" + +## Any #tags that were included in the line +var tags: PackedStringArray = [] + +## The mutation details if this is a mutation line (where [code]type == TYPE_MUTATION[/code]). +var mutation: Dictionary = {} + +## The conditions to check before including this line in the flow of dialogue. If failed the line will be skipped over. +var conditions: Dictionary = {} + + +func _init(data: Dictionary = {}) -> void: + if data.size() > 0: + id = data.id + next_id = data.next_id + type = data.type + extra_game_states = data.get("extra_game_states", []) + + match type: + _DialogueConstants.TYPE_DIALOGUE: + character = data.character + character_replacements = data.get("character_replacements", [] as Array[Dictionary]) + text = data.text + text_replacements = data.get("text_replacements", [] as Array[Dictionary]) + translation_key = data.get("translation_key", data.text) + pauses = data.get("pauses", {}) + speeds = data.get("speeds", {}) + inline_mutations = data.get("inline_mutations", [] as Array[Array]) + time = data.get("time", "") + tags = data.get("tags", []) + + _DialogueConstants.TYPE_MUTATION: + mutation = data.mutation + + +func _to_string() -> String: + match type: + _DialogueConstants.TYPE_DIALOGUE: + return "<DialogueLine character=\"%s\" text=\"%s\">" % [character, text] + _DialogueConstants.TYPE_MUTATION: + return "<DialogueLine mutation>" + return "" + + +func get_tag_value(tag_name: String) -> String: + var wrapped := "%s=" % tag_name + for t in tags: + if t.begins_with(wrapped): + return t.replace(wrapped, "").strip_edges() + return "" diff --git a/addons/dialogue_manager/dialogue_manager.gd b/addons/dialogue_manager/dialogue_manager.gd new file mode 100644 index 0000000..57d7f86 --- /dev/null +++ b/addons/dialogue_manager/dialogue_manager.gd @@ -0,0 +1,1235 @@ +extends Node + + +const DialogueConstants = preload("./constants.gd") +const Builtins = preload("./utilities/builtins.gd") +const DialogueSettings = preload("./settings.gd") +const DialogueResource = preload("./dialogue_resource.gd") +const DialogueLine = preload("./dialogue_line.gd") +const DialogueResponse = preload("./dialogue_response.gd") +const DialogueManagerParser = preload("./components/parser.gd") +const DialogueManagerParseResult = preload("./components/parse_result.gd") +const ResolvedLineData = preload("./components/resolved_line_data.gd") + + +## Emitted when a title is encountered while traversing dialogue, usually when jumping from a +## goto line +signal passed_title(title: String) + +## Emitted when a line of dialogue is encountered. +signal got_dialogue(line: DialogueLine) + +## Emitted when a mutation is encountered. +signal mutated(mutation: Dictionary) + +## Emitted when some dialogue has reached the end. +signal dialogue_ended(resource: DialogueResource) + +## Used internally. +signal bridge_get_next_dialogue_line_completed(line: DialogueLine) + +## Used inernally +signal bridge_mutated() + + +enum MutationBehaviour { + Wait, + DoNotWait, + Skip +} + +enum TranslationSource { + None, + Guess, + CSV, + PO +} + + +## The list of globals that dialogue can query +var game_states: Array = [] + +## Allow dialogue to call singletons +var include_singletons: bool = true + +## Allow dialogue to call static methods/properties on classes +var include_classes: bool = true + +## Manage translation behaviour +var translation_source: TranslationSource = TranslationSource.Guess + +## Used to resolve the current scene. Override if your game manages the current scene itself. +var get_current_scene: Callable = func(): + var current_scene: Node = get_tree().current_scene + if current_scene == null: + current_scene = get_tree().root.get_child(get_tree().root.get_child_count() - 1) + return current_scene + +var _has_loaded_autoloads: bool = false +var _autoloads: Dictionary = {} + + +var _node_properties: Array = [] + + +func _ready() -> void: + # Cache the known Node2D properties + _node_properties = ["Script Variables"] + var temp_node: Node2D = Node2D.new() + for property in temp_node.get_property_list(): + _node_properties.append(property.name) + temp_node.free() + + # Make the dialogue manager available as a singleton + if Engine.has_singleton("DialogueManager"): + Engine.unregister_singleton("DialogueManager") + Engine.register_singleton("DialogueManager", self) + + # Connect up the C# signals if need be + if DialogueSettings.has_dotnet_solution(): + _get_dotnet_dialogue_manager().Prepare() + + +## Step through lines and run any mutations until we either hit some dialogue or the end of the conversation +func get_next_dialogue_line(resource: DialogueResource, key: String = "", extra_game_states: Array = [], mutation_behaviour: MutationBehaviour = MutationBehaviour.Wait) -> DialogueLine: + # You have to provide a valid dialogue resource + if resource == null: + assert(false, DialogueConstants.translate(&"runtime.no_resource")) + if resource.lines.size() == 0: + assert(false, DialogueConstants.translate(&"runtime.no_content").format({ file_path = resource.resource_path })) + + # Inject any "using" states into the game_states + for state_name in resource.using_states: + var autoload = get_tree().root.get_node_or_null(state_name) + if autoload == null: + printerr(DialogueConstants.translate(&"runtime.unknown_autoload").format({ autoload = state_name })) + else: + extra_game_states = [autoload] + extra_game_states + + # Get the line data + var dialogue: DialogueLine = await get_line(resource, key, extra_game_states) + + # If our dialogue is nothing then we hit the end + if not is_valid(dialogue): + (func(): dialogue_ended.emit(resource)).call_deferred() + return null + + # Run the mutation if it is one + if dialogue.type == DialogueConstants.TYPE_MUTATION: + var actual_next_id: String = dialogue.next_id.split(",")[0] + match mutation_behaviour: + MutationBehaviour.Wait: + await mutate(dialogue.mutation, extra_game_states) + MutationBehaviour.DoNotWait: + mutate(dialogue.mutation, extra_game_states) + MutationBehaviour.Skip: + pass + if actual_next_id in [DialogueConstants.ID_END_CONVERSATION, DialogueConstants.ID_NULL, null]: + # End the conversation + (func(): dialogue_ended.emit(resource)).call_deferred() + return null + else: + return await get_next_dialogue_line(resource, dialogue.next_id, extra_game_states, mutation_behaviour) + else: + got_dialogue.emit(dialogue) + return dialogue + + +func get_resolved_line_data(data: Dictionary, extra_game_states: Array = []) -> ResolvedLineData: + var text: String = translate(data) + + # Resolve variables + for replacement in data.text_replacements: + var value = await resolve(replacement.expression.duplicate(true), extra_game_states) + var index: int = text.find(replacement.value_in_text) + text = text.substr(0, index) + str(value) + text.substr(index + replacement.value_in_text.length()) + + var parser: DialogueManagerParser = DialogueManagerParser.new() + + # Resolve random groups + for found in parser.INLINE_RANDOM_REGEX.search_all(text): + var options = found.get_string(&"options").split(&"|") + text = text.replace(&"[[%s]]" % found.get_string(&"options"), options[randi_range(0, options.size() - 1)]) + + # Do a pass on the markers to find any conditionals + var markers: ResolvedLineData = parser.extract_markers(text) + + # Resolve any conditionals and update marker positions as needed + if data.type == DialogueConstants.TYPE_DIALOGUE: + var resolved_text: String = markers.text + var conditionals: Array[RegExMatch] = parser.INLINE_CONDITIONALS_REGEX.search_all(resolved_text) + var replacements: Array = [] + for conditional in conditionals: + var condition_raw: String = conditional.strings[conditional.names.condition] + var body: String = conditional.strings[conditional.names.body] + var body_else: String = "" + if &"[else]" in body: + var bits = body.split(&"[else]") + body = bits[0] + body_else = bits[1] + var condition: Dictionary = parser.extract_condition("if " + condition_raw, false, 0) + # If the condition fails then use the else of "" + if not await check_condition({ condition = condition }, extra_game_states): + body = body_else + replacements.append({ + start = conditional.get_start(), + end = conditional.get_end(), + string = conditional.get_string(), + body = body + }) + + for i in range(replacements.size() -1, -1, -1): + var r: Dictionary = replacements[i] + resolved_text = resolved_text.substr(0, r.start) + r.body + resolved_text.substr(r.end, 9999) + # Move any other markers now that the text has changed + var offset: int = r.end - r.start - r.body.length() + for key in [&"pauses", &"speeds", &"time"]: + if markers.get(key) == null: continue + var marker = markers.get(key) + var next_marker: Dictionary = {} + for index in marker: + if index < r.start: + next_marker[index] = marker[index] + elif index > r.start: + next_marker[index - offset] = marker[index] + markers.set(key, next_marker) + var mutations: Array[Array] = markers.mutations + var next_mutations: Array[Array] = [] + for mutation in mutations: + var index = mutation[0] + if index < r.start: + next_mutations.append(mutation) + elif index > r.start: + next_mutations.append([index - offset, mutation[1]]) + markers.mutations = next_mutations + + markers.text = resolved_text + + parser.free() + + return markers + + +## Replace any variables, etc in the character name +func get_resolved_character(data: Dictionary, extra_game_states: Array = []) -> String: + var character: String = data.get(&"character", "") + + # Resolve variables + for replacement in data.get(&"character_replacements", []): + var value = await resolve(replacement.expression.duplicate(true), extra_game_states) + var index: int = character.find(replacement.value_in_text) + character = character.substr(0, index) + str(value) + character.substr(index + replacement.value_in_text.length()) + + # Resolve random groups + var random_regex: RegEx = RegEx.new() + random_regex.compile("\\[\\[(?<options>.*?)\\]\\]") + for found in random_regex.search_all(character): + var options = found.get_string(&"options").split("|") + character = character.replace("[[%s]]" % found.get_string(&"options"), options[randi_range(0, options.size() - 1)]) + + return character + + +## Generate a dialogue resource on the fly from some text +func create_resource_from_text(text: String) -> Resource: + var parser: DialogueManagerParser = DialogueManagerParser.new() + parser.parse(text, "") + var results: DialogueManagerParseResult = parser.get_data() + var errors: Array[Dictionary] = parser.get_errors() + parser.free() + + if errors.size() > 0: + printerr(DialogueConstants.translate(&"runtime.errors").format({ count = errors.size() })) + for error in errors: + printerr(DialogueConstants.translate(&"runtime.error_detail").format({ + line = error.line_number + 1, + message = DialogueConstants.get_error_message(error.error) + })) + assert(false, DialogueConstants.translate(&"runtime.errors_see_details").format({ count = errors.size() })) + + var resource: DialogueResource = DialogueResource.new() + resource.using_states = results.using_states + resource.titles = results.titles + resource.first_title = results.first_title + resource.character_names = results.character_names + resource.lines = results.lines + resource.raw_text = text + + return resource + + +## Show the example balloon +func show_example_dialogue_balloon(resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> CanvasLayer: + var balloon: Node = load(_get_example_balloon_path()).instantiate() + get_current_scene.call().add_child(balloon) + balloon.start(resource, title, extra_game_states) + + return balloon + + +## Show the configured dialogue balloon +func show_dialogue_balloon(resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> Node: + var balloon_path: String = DialogueSettings.get_setting(&"balloon_path", _get_example_balloon_path()) + if not ResourceLoader.exists(balloon_path): + balloon_path = _get_example_balloon_path() + return show_dialogue_balloon_scene(balloon_path, resource, title, extra_game_states) + + +## Show a given balloon scene +func show_dialogue_balloon_scene(balloon_scene, resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> Node: + if balloon_scene is String: + balloon_scene = load(balloon_scene) + if balloon_scene is PackedScene: + balloon_scene = balloon_scene.instantiate() + + var balloon: Node = balloon_scene + get_current_scene.call().add_child(balloon) + if balloon.has_method(&"start"): + balloon.start(resource, title, extra_game_states) + elif balloon.has_method(&"Start"): + balloon.Start(resource, title, extra_game_states) + else: + assert(false, DialogueConstants.translate(&"runtime.dialogue_balloon_missing_start_method")) + return balloon + + +# Get the path to the example balloon +func _get_example_balloon_path() -> String: + var is_small_window: bool = ProjectSettings.get_setting("display/window/size/viewport_width") < 400 + var balloon_path: String = "/example_balloon/small_example_balloon.tscn" if is_small_window else "/example_balloon/example_balloon.tscn" + return get_script().resource_path.get_base_dir() + balloon_path + + +### Dotnet bridge + + +func _get_dotnet_dialogue_manager() -> Node: + return load(get_script().resource_path.get_base_dir() + "/DialogueManager.cs").new() + + +func _bridge_get_next_dialogue_line(resource: DialogueResource, key: String, extra_game_states: Array = []) -> void: + # dotnet needs at least one await tick of the signal gets called too quickly + await get_tree().process_frame + + var line = await get_next_dialogue_line(resource, key, extra_game_states) + bridge_get_next_dialogue_line_completed.emit(line) + + +func _bridge_mutate(mutation: Dictionary, extra_game_states: Array, is_inline_mutation: bool = false) -> void: + await mutate(mutation, extra_game_states, is_inline_mutation) + bridge_mutated.emit() + + +### Helpers + + +# Get a line by its ID +func get_line(resource: DialogueResource, key: String, extra_game_states: Array) -> DialogueLine: + key = key.strip_edges() + + # See if we were given a stack instead of just the one key + var stack: Array = key.split("|") + key = stack.pop_front() + var id_trail: String = "" if stack.size() == 0 else "|" + "|".join(stack) + + # Key is blank so just use the first title + if key == null or key == "": + key = resource.first_title + + # See if we just ended the conversation + if key in [DialogueConstants.ID_END, DialogueConstants.ID_NULL, null]: + if stack.size() > 0: + return await get_line(resource, "|".join(stack), extra_game_states) + else: + return null + elif key == DialogueConstants.ID_END_CONVERSATION: + return null + + # See if it is a title + if key.begins_with("~ "): + key = key.substr(2) + if resource.titles.has(key): + key = resource.titles.get(key) + + if key in resource.titles.values(): + passed_title.emit(resource.titles.find_key(key)) + + if not resource.lines.has(key): + assert(false, DialogueConstants.translate(&"errors.key_not_found").format({ key = key })) + + var data: Dictionary = resource.lines.get(key) + + # Check for weighted random lines + if data.has(&"siblings"): + var target_weight: float = randf_range(0, data.siblings.reduce(func(total, sibling): return total + sibling.weight, 0)) + var cummulative_weight: float = 0 + for sibling in data.siblings: + if target_weight < cummulative_weight + sibling.weight: + data = resource.lines.get(sibling.id) + break + else: + cummulative_weight += sibling.weight + + # Check condtiions + if data.type == DialogueConstants.TYPE_CONDITION: + # "else" will have no actual condition + if await check_condition(data, extra_game_states): + return await get_line(resource, data.next_id + id_trail, extra_game_states) + else: + return await get_line(resource, data.next_conditional_id + id_trail, extra_game_states) + + # Evaluate jumps + elif data.type == DialogueConstants.TYPE_GOTO: + if data.is_snippet: + id_trail = "|" + data.next_id_after + id_trail + return await get_line(resource, data.next_id + id_trail, extra_game_states) + + elif data.type == DialogueConstants.TYPE_DIALOGUE: + if not data.has(&"id"): + data.id = key + + # Set up a line object + var line: DialogueLine = await create_dialogue_line(data, extra_game_states) + + # If the jump point somehow has no content then just end + if not line: return null + + # If we are the first of a list of responses then get the other ones + if data.type == DialogueConstants.TYPE_RESPONSE: + # Note: For some reason C# has occasional issues with using the responses property directly + # so instead we use set and get here. + line.set(&"responses", await get_responses(data.get(&"responses", []), resource, id_trail, extra_game_states)) + return line + + # Inject the next node's responses if they have any + if resource.lines.has(line.next_id): + var next_line: Dictionary = resource.lines.get(line.next_id) + + # If the response line is marked as a title then make sure to emit the passed_title signal. + if line.next_id in resource.titles.values(): + passed_title.emit(resource.titles.find_key(line.next_id)) + + # If the next line is a title then check where it points to see if that is a set of responses. + if next_line.type == DialogueConstants.TYPE_GOTO and resource.lines.has(next_line.next_id): + next_line = resource.lines.get(next_line.next_id) + + if next_line != null and next_line.type == DialogueConstants.TYPE_RESPONSE: + # Note: For some reason C# has occasional issues with using the responses property directly + # so instead we use set and get here. + line.set(&"responses", await get_responses(next_line.get(&"responses", []), resource, id_trail, extra_game_states)) + + line.next_id = "|".join(stack) if line.next_id == DialogueConstants.ID_NULL else line.next_id + id_trail + return line + + +# Show a message or crash with error +func show_error_for_missing_state_value(message: String, will_show: bool = true) -> void: + if not will_show: return + + if DialogueSettings.get_setting(&"ignore_missing_state_values", false): + push_error(message) + elif will_show: + # If you're here then you're missing a method or property in your game state. The error + # message down in the debugger will give you some more information. + assert(false, message) + + +# Translate a string +func translate(data: Dictionary) -> String: + if translation_source == TranslationSource.None: + return data.text + + if data.translation_key == "" or data.translation_key == data.text: + return tr(data.text) + else: + # Line IDs work slightly differently depending on whether the translation came from a + # CSV or a PO file. CSVs use the line ID (or the line itself) as the translatable string + # whereas POs use the ID as context and the line itself as the translatable string. + match translation_source: + TranslationSource.PO: + return tr(data.text, StringName(data.translation_key)) + + TranslationSource.CSV: + return tr(data.translation_key) + + TranslationSource.Guess: + var translation_files: Array = ProjectSettings.get_setting(&"internationalization/locale/translations") + if translation_files.filter(func(f: String): return f.get_extension() == &"po").size() > 0: + # Assume PO + return tr(data.text, StringName(data.translation_key)) + else: + # Assume CSV + return tr(data.translation_key) + + return tr(data.translation_key) + + +# Create a line of dialogue +func create_dialogue_line(data: Dictionary, extra_game_states: Array) -> DialogueLine: + match data.type: + DialogueConstants.TYPE_DIALOGUE: + var resolved_data: ResolvedLineData = await get_resolved_line_data(data, extra_game_states) + return DialogueLine.new({ + id = data.get(&"id", ""), + type = DialogueConstants.TYPE_DIALOGUE, + next_id = data.next_id, + character = await get_resolved_character(data, extra_game_states), + character_replacements = data.character_replacements, + text = resolved_data.text, + text_replacements = data.text_replacements, + translation_key = data.translation_key, + pauses = resolved_data.pauses, + speeds = resolved_data.speeds, + inline_mutations = resolved_data.mutations, + time = resolved_data.time, + tags = data.get(&"tags", []), + extra_game_states = extra_game_states + }) + + DialogueConstants.TYPE_RESPONSE: + return DialogueLine.new({ + id = data.get(&"id", ""), + type = DialogueConstants.TYPE_RESPONSE, + next_id = data.next_id, + tags = data.get(&"tags", []), + extra_game_states = extra_game_states + }) + + DialogueConstants.TYPE_MUTATION: + return DialogueLine.new({ + id = data.get(&"id", ""), + type = DialogueConstants.TYPE_MUTATION, + next_id = data.next_id, + mutation = data.mutation, + extra_game_states = extra_game_states + }) + + return null + + +# Create a response +func create_response(data: Dictionary, extra_game_states: Array) -> DialogueResponse: + var resolved_data: ResolvedLineData = await get_resolved_line_data(data, extra_game_states) + return DialogueResponse.new({ + id = data.get(&"id", ""), + type = DialogueConstants.TYPE_RESPONSE, + next_id = data.next_id, + is_allowed = data.is_allowed, + character = await get_resolved_character(data, extra_game_states), + character_replacements = data.get(&"character_replacements", [] as Array[Dictionary]), + text = resolved_data.text, + text_replacements = data.text_replacements, + tags = data.get(&"tags", []), + translation_key = data.translation_key + }) + + +# Get the current game states +func get_game_states(extra_game_states: Array) -> Array: + if not _has_loaded_autoloads: + _has_loaded_autoloads = true + # Add any autoloads to a generic state so we can refer to them by name + for child in get_tree().root.get_children(): + # Ignore the dialogue manager + if child.name == &"DialogueManager": continue + # Ignore the current main scene + if get_tree().current_scene and child.name == get_tree().current_scene.name: continue + # Add the node to our known autoloads + _autoloads[child.name] = child + game_states = [_autoloads] + # Add any other state shortcuts from settings + for node_name in DialogueSettings.get_setting(&"states", []): + var state: Node = get_node_or_null("/root/" + node_name) + if state: + game_states.append(state) + + var current_scene: Node = get_current_scene.call() + var unique_states: Array = [] + for state in extra_game_states + [current_scene] + game_states: + if state != null and not unique_states.has(state): + unique_states.append(state) + return unique_states + + +# Check if a condition is met +func check_condition(data: Dictionary, extra_game_states: Array) -> bool: + if data.get(&"condition", null) == null: return true + if data.condition.size() == 0: return true + + return await resolve(data.condition.expression.duplicate(true), extra_game_states) + + +# Make a change to game state or run a method +func mutate(mutation: Dictionary, extra_game_states: Array, is_inline_mutation: bool = false) -> void: + var expression: Array[Dictionary] = mutation.expression + + # Handle built in mutations + if expression[0].type == DialogueConstants.TOKEN_FUNCTION and expression[0].function in [&"wait", &"debug"]: + var args: Array = await resolve_each(expression[0].value, extra_game_states) + match expression[0].function: + &"wait": + mutated.emit(mutation) + await get_tree().create_timer(float(args[0])).timeout + return + + &"debug": + prints("Debug:", args) + await get_tree().process_frame + + # Or pass through to the resolver + else: + if not mutation_contains_assignment(mutation.expression) and not is_inline_mutation: + mutated.emit(mutation) + + if mutation.get("is_blocking", true): + await resolve(mutation.expression.duplicate(true), extra_game_states) + return + else: + resolve(mutation.expression.duplicate(true), extra_game_states) + + # Wait one frame to give the dialogue handler a chance to yield + await get_tree().process_frame + + +func mutation_contains_assignment(mutation: Array) -> bool: + for token in mutation: + if token.type == DialogueConstants.TOKEN_ASSIGNMENT: + return true + return false + + +func resolve_each(array: Array, extra_game_states: Array) -> Array: + var results: Array = [] + for item in array: + results.append(await resolve(item.duplicate(true), extra_game_states)) + return results + + +# Replace an array of line IDs with their response prompts +func get_responses(ids: Array, resource: DialogueResource, id_trail: String, extra_game_states: Array) -> Array[DialogueResponse]: + var responses: Array[DialogueResponse] = [] + for id in ids: + var data: Dictionary = resource.lines.get(id).duplicate(true) + data.is_allowed = await check_condition(data, extra_game_states) + if DialogueSettings.get_setting(&"include_all_responses", false) or data.is_allowed: + var response: DialogueResponse = await create_response(data, extra_game_states) + response.next_id += id_trail + responses.append(response) + + return responses + + +# Get a value on the current scene or game state +func get_state_value(property: String, extra_game_states: Array): + # Special case for static primitive calls + if property == "Color": + return Color() + elif property == "Vector2": + return Vector2.ZERO + elif property == "Vector3": + return Vector3.ZERO + elif property == "Vector4": + return Vector4.ZERO + elif property == "Quaternian": + return Quaternion() + + var expression = Expression.new() + if expression.parse(property) != OK: + assert(false, DialogueConstants.translate(&"runtime.invalid_expression").format({ expression = property, error = expression.get_error_text() })) + + for state in get_game_states(extra_game_states): + if typeof(state) == TYPE_DICTIONARY: + if state.has(property): + return state.get(property) + else: + var result = expression.execute([], state, false) + if not expression.has_execute_failed(): + return result + + if include_singletons and Engine.has_singleton(property): + return Engine.get_singleton(property) + + if include_classes: + for class_data in ProjectSettings.get_global_class_list(): + if class_data.get(&"class") == property: + return load(class_data.path).new() + + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found").format({ property = property, states = str(get_game_states(extra_game_states)) })) + + +# Set a value on the current scene or game state +func set_state_value(property: String, value, extra_game_states: Array) -> void: + for state in get_game_states(extra_game_states): + if typeof(state) == TYPE_DICTIONARY: + if state.has(property): + state[property] = value + return + elif thing_has_property(state, property): + state.set(property, value) + return + + if property.to_snake_case() != property: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found_missing_export").format({ property = property, states = str(get_game_states(extra_game_states)) })) + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found").format({ property = property, states = str(get_game_states(extra_game_states)) })) + + +# Collapse any expressions +func resolve(tokens: Array, extra_game_states: Array): + # Handle groups first + for token in tokens: + if token.type == DialogueConstants.TOKEN_GROUP: + token["type"] = "value" + token["value"] = await resolve(token.value, extra_game_states) + + # Then variables/methods + var i: int = 0 + var limit: int = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + + if token.type == DialogueConstants.TOKEN_FUNCTION: + var function_name: String = token.function + var args = await resolve_each(token.value, extra_game_states) + if tokens[i - 1].type == DialogueConstants.TOKEN_DOT: + # If we are calling a deeper function then we need to collapse the + # value into the thing we are calling the function on + var caller: Dictionary = tokens[i - 2] + if Builtins.is_supported(caller.value): + caller["type"] = "value" + caller["value"] = Builtins.resolve_method(caller.value, function_name, args) + tokens.remove_at(i) + tokens.remove_at(i-1) + i -= 2 + elif thing_has_method(caller.value, function_name, args): + caller["type"] = "value" + caller["value"] = await resolve_thing_method(caller.value, function_name, args) + tokens.remove_at(i) + tokens.remove_at(i-1) + i -= 2 + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.method_not_callable").format({ method = function_name, object = str(caller.value) })) + else: + var found: bool = false + match function_name: + &"str": + token["type"] = "value" + token["value"] = str(args[0]) + found = true + &"Vector2": + token["type"] = "value" + token["value"] = Vector2(args[0], args[1]) + found = true + &"Vector2i": + token["type"] = "value" + token["value"] = Vector2i(args[0], args[1]) + found = true + &"Vector3": + token["type"] = "value" + token["value"] = Vector3(args[0], args[1], args[2]) + found = true + &"Vector3i": + token["type"] = "value" + token["value"] = Vector3i(args[0], args[1], args[2]) + found = true + &"Vector4": + token["type"] = "value" + token["value"] = Vector4(args[0], args[1], args[2], args[3]) + found = true + &"Vector4i": + token["type"] = "value" + token["value"] = Vector4i(args[0], args[1], args[2], args[3]) + found = true + &"Quaternion": + token["type"] = "value" + token["value"] = Quaternion(args[0], args[1], args[2], args[3]) + found = true + &"Color": + token["type"] = "value" + match args.size(): + 0: + token["value"] = Color() + 1: + token["value"] = Color(args[0]) + 2: + token["value"] = Color(args[0], args[1]) + 3: + token["value"] = Color(args[0], args[1], args[2]) + 4: + token["value"] = Color(args[0], args[1], args[2], args[3]) + found = true + &"load": + token["type"] = "value" + token["value"] = load(args[0]) + found = true + &"emit": + token["type"] = "value" + token["value"] = resolve_signal(args, extra_game_states) + found = true + _: + for state in get_game_states(extra_game_states): + if thing_has_method(state, function_name, args): + token["type"] = "value" + token["value"] = await resolve_thing_method(state, function_name, args) + found = true + break + + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.method_not_found").format({ + method = args[0] if function_name in ["call", "call_deferred"] else function_name, + states = str(get_game_states(extra_game_states)) + }), not found) + + elif token.type == DialogueConstants.TOKEN_DICTIONARY_REFERENCE: + var value + if i > 0 and tokens[i - 1].type == DialogueConstants.TOKEN_DOT: + # If we are deep referencing then we need to get the parent object. + # `parent.value` is the actual object and `token.variable` is the name of + # the property within it. + value = tokens[i - 2].value[token.variable] + # Clean up the previous tokens + token.erase("variable") + tokens.remove_at(i - 1) + tokens.remove_at(i - 2) + i -= 2 + else: + # Otherwise we can just get this variable as a normal state reference + value = get_state_value(token.variable, extra_game_states) + + var index = await resolve(token.value, extra_game_states) + if typeof(value) == TYPE_DICTIONARY: + if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # If the next token is an assignment then we need to leave this as a reference + # so that it can be resolved once everything ahead of it has been resolved + token["type"] = "dictionary" + token["value"] = value + token["key"] = index + else: + if value.has(index): + token["type"] = "value" + token["value"] = value[index] + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.key_not_found").format({ key = str(index), dictionary = token.variable })) + elif typeof(value) == TYPE_ARRAY: + if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # If the next token is an assignment then we need to leave this as a reference + # so that it can be resolved once everything ahead of it has been resolved + token["type"] = "array" + token["value"] = value + token["key"] = index + else: + if index >= 0 and index < value.size(): + token["type"] = "value" + token["value"] = value[index] + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = index, array = token.variable })) + + elif token.type == DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE: + var dictionary: Dictionary = tokens[i - 1] + var index = await resolve(token.value, extra_game_states) + var value = dictionary.value + if typeof(value) == TYPE_DICTIONARY: + if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # If the next token is an assignment then we need to leave this as a reference + # so that it can be resolved once everything ahead of it has been resolved + dictionary["type"] = "dictionary" + dictionary["key"] = index + dictionary["value"] = value + tokens.remove_at(i) + i -= 1 + else: + if dictionary.value.has(index): + dictionary["value"] = value.get(index) + tokens.remove_at(i) + i -= 1 + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.key_not_found").format({ key = str(index), dictionary = value })) + elif typeof(value) == TYPE_ARRAY: + if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # If the next token is an assignment then we need to leave this as a reference + # so that it can be resolved once everything ahead of it has been resolved + dictionary["type"] = "array" + dictionary["value"] = value + dictionary["key"] = index + tokens.remove_at(i) + i -= 1 + else: + if index >= 0 and index < value.size(): + dictionary["value"] = value[index] + tokens.remove_at(i) + i -= 1 + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = index, array = value })) + + elif token.type == DialogueConstants.TOKEN_ARRAY: + token["type"] = "value" + token["value"] = await resolve_each(token.value, extra_game_states) + + elif token.type == DialogueConstants.TOKEN_DICTIONARY: + token["type"] = "value" + var dictionary = {} + for key in token.value.keys(): + var resolved_key = await resolve([key], extra_game_states) + var preresolved_value = token.value.get(key) + if typeof(preresolved_value) != TYPE_ARRAY: + preresolved_value = [preresolved_value] + var resolved_value = await resolve(preresolved_value, extra_game_states) + dictionary[resolved_key] = resolved_value + token["value"] = dictionary + + elif token.type == DialogueConstants.TOKEN_VARIABLE or token.type == DialogueConstants.TOKEN_NUMBER: + if str(token.value) == "null": + token["type"] = "value" + token["value"] = null + elif tokens[i - 1].type == DialogueConstants.TOKEN_DOT: + var caller: Dictionary = tokens[i - 2] + var property = token.value + if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # If the next token is an assignment then we need to leave this as a reference + # so that it can be resolved once everything ahead of it has been resolved + caller["type"] = "property" + caller["property"] = property + else: + # If we are requesting a deeper property then we need to collapse the + # value into the thing we are referencing from + caller["type"] = "value" + if Builtins.is_supported(caller.value): + caller["value"] = Builtins.resolve_property(caller.value, property) + else: + caller["value"] = caller.value.get(property) + tokens.remove_at(i) + tokens.remove_at(i-1) + i -= 2 + elif tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # It's a normal variable but we will be assigning to it so don't resolve + # it until everything after it has been resolved + token["type"] = "variable" + else: + token["type"] = "value" + token["value"] = get_state_value(str(token.value), extra_game_states) + + i += 1 + + # Then multiply and divide + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_OPERATOR and token.value in ["*", "/", "%"]: + token["type"] = "value" + token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) + tokens.remove_at(i+1) + tokens.remove_at(i-1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + # Then addition and subtraction + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_OPERATOR and token.value in ["+", "-"]: + token["type"] = "value" + token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) + tokens.remove_at(i+1) + tokens.remove_at(i-1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + # Then negations + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_NOT: + token["type"] = "value" + token["value"] = not tokens[i+1].value + tokens.remove_at(i+1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + # Then comparisons + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_COMPARISON: + token["type"] = "value" + token["value"] = compare(token.value, tokens[i-1].value, tokens[i+1].value) + tokens.remove_at(i+1) + tokens.remove_at(i-1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + # Then and/or + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_AND_OR: + token["type"] = "value" + token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) + tokens.remove_at(i+1) + tokens.remove_at(i-1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + # Lastly, resolve any assignments + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_ASSIGNMENT: + var lhs: Dictionary = tokens[i - 1] + var value + + match lhs.type: + &"variable": + value = apply_operation(token.value, get_state_value(lhs.value, extra_game_states), tokens[i+1].value) + set_state_value(lhs.value, value, extra_game_states) + &"property": + value = apply_operation(token.value, lhs.value.get(lhs.property), tokens[i+1].value) + if typeof(lhs.value) == TYPE_DICTIONARY: + lhs.value[lhs.property] = value + else: + lhs.value.set(lhs.property, value) + &"dictionary": + value = apply_operation(token.value, lhs.value.get(lhs.key, null), tokens[i+1].value) + lhs.value[lhs.key] = value + &"array": + show_error_for_missing_state_value( + DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = lhs.key, array = lhs.value }), + lhs.key >= lhs.value.size() + ) + value = apply_operation(token.value, lhs.value[lhs.key], tokens[i+1].value) + lhs.value[lhs.key] = value + _: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.left_hand_size_cannot_be_assigned_to")) + + token["type"] = "value" + token["value"] = value + tokens.remove_at(i+1) + tokens.remove_at(i-1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + return tokens[0].value + + +func compare(operator: String, first_value, second_value) -> bool: + match operator: + &"in": + if first_value == null or second_value == null: + return false + else: + return first_value in second_value + &"<": + if first_value == null: + return true + elif second_value == null: + return false + else: + return first_value < second_value + &">": + if first_value == null: + return false + elif second_value == null: + return true + else: + return first_value > second_value + &"<=": + if first_value == null: + return true + elif second_value == null: + return false + else: + return first_value <= second_value + &">=": + if first_value == null: + return false + elif second_value == null: + return true + else: + return first_value >= second_value + &"==": + if first_value == null: + if typeof(second_value) == TYPE_BOOL: + return second_value == false + else: + return second_value == null + else: + return first_value == second_value + &"!=": + if first_value == null: + if typeof(second_value) == TYPE_BOOL: + return second_value == true + else: + return second_value != null + else: + return first_value != second_value + + return false + + +func apply_operation(operator: String, first_value, second_value): + match operator: + &"=": + return second_value + &"+", &"+=": + return first_value + second_value + &"-", &"-=": + return first_value - second_value + &"/", &"/=": + return first_value / second_value + &"*", &"*=": + return first_value * second_value + &"%": + return first_value % second_value + &"and": + return first_value and second_value + &"or": + return first_value or second_value + + assert(false, DialogueConstants.translate(&"runtime.unknown_operator")) + + +# Check if a dialogue line contains meaningful information +func is_valid(line: DialogueLine) -> bool: + if line == null: + return false + if line.type == DialogueConstants.TYPE_MUTATION and line.mutation == null: + return false + if line.type == DialogueConstants.TYPE_RESPONSE and line.get(&"responses").size() == 0: + return false + return true + + +func thing_has_method(thing, method: String, args: Array) -> bool: + if Builtins.is_supported(thing): + return thing != _autoloads + + if method in [&"call", &"call_deferred"]: + return thing.has_method(args[0]) + + if method == &"emit_signal": + return thing.has_signal(args[0]) + + if thing.has_method(method): + return true + + if method.to_snake_case() != method and DialogueSettings.has_dotnet_solution(): + # If we get this far then the method might be a C# method with a Task return type + return _get_dotnet_dialogue_manager().ThingHasMethod(thing, method) + + return false + + +# Check if a given property exists +func thing_has_property(thing: Object, property: String) -> bool: + if thing == null: + return false + + for p in thing.get_property_list(): + if _node_properties.has(p.name): + # Ignore any properties on the base Node + continue + if p.name == property: + return true + + return false + + +func resolve_signal(args: Array, extra_game_states: Array): + if args[0] is Signal: + args[0] = args[0].get_name() + + for state in get_game_states(extra_game_states): + if typeof(state) == TYPE_DICTIONARY: + continue + elif state.has_signal(args[0]): + match args.size(): + 1: + state.emit_signal(args[0]) + 2: + state.emit_signal(args[0], args[1]) + 3: + state.emit_signal(args[0], args[1], args[2]) + 4: + state.emit_signal(args[0], args[1], args[2], args[3]) + 5: + state.emit_signal(args[0], args[1], args[2], args[3], args[4]) + 6: + state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5]) + 7: + state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5], args[6]) + 8: + state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]) + return + + # The signal hasn't been found anywhere + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.signal_not_found").format({ signal_name = args[0], states = str(get_game_states(extra_game_states)) })) + + +func resolve_thing_method(thing, method: String, args: Array): + if Builtins.is_supported(thing): + var result = Builtins.resolve_method(thing, method, args) + if not Builtins.has_resolve_method_failed(): + return result + + if thing.has_method(method): + # Try to convert any literals to the right type + var method_info: Dictionary = thing.get_method_list().filter(func(m): return method == m.name)[0] + var method_args: Array = method_info.args + if method_info.flags & METHOD_FLAG_VARARG == 0 and method_args.size() < args.size(): + assert(false, DialogueConstants.translate(&"runtime.expected_n_got_n_args").format({ expected = method_args.size(), method = method, received = args.size()})) + for i in range(0, args.size()): + var m: Dictionary = method_args[i] + var to_type:int = typeof(args[i]) + if m.type == TYPE_ARRAY: + match m.hint_string: + &"String": + to_type = TYPE_PACKED_STRING_ARRAY + &"int": + to_type = TYPE_PACKED_INT64_ARRAY + &"float": + to_type = TYPE_PACKED_FLOAT64_ARRAY + &"Vector2": + to_type = TYPE_PACKED_VECTOR2_ARRAY + &"Vector3": + to_type = TYPE_PACKED_VECTOR3_ARRAY + _: + if m.hint_string != "": + assert(false, DialogueConstants.translate(&"runtime.unsupported_array_type").format({ type = m.hint_string})) + if typeof(args[i]) != to_type: + args[i] = convert(args[i], to_type) + + return await thing.callv(method, args) + + # If we get here then it's probably a C# method with a Task return type + var dotnet_dialogue_manager = _get_dotnet_dialogue_manager() + dotnet_dialogue_manager.ResolveThingMethod(thing, method, args) + return await dotnet_dialogue_manager.Resolved diff --git a/addons/dialogue_manager/dialogue_reponses_menu.gd b/addons/dialogue_manager/dialogue_reponses_menu.gd new file mode 100644 index 0000000..6da0e5c --- /dev/null +++ b/addons/dialogue_manager/dialogue_reponses_menu.gd @@ -0,0 +1,131 @@ +@icon("./assets/responses_menu.svg") + +## A VBoxContainer for dialogue responses provided by [b]Dialogue Manager[/b]. +class_name DialogueResponsesMenu extends VBoxContainer + + +## Emitted when a response is selected. +signal response_selected(response) + + +## Optionally specify a control to duplicate for each response +@export var response_template: Control + +## The action for accepting a response (is possibly overridden by parent dialogue balloon). +@export var next_action: StringName = &"" + +# The list of dialogue responses. +var responses: Array = []: + set(value): + responses = value + + # Remove any current items + for item in get_children(): + if item == response_template: continue + + remove_child(item) + item.queue_free() + + # Add new items + if responses.size() > 0: + for response in responses: + var item: Control + if is_instance_valid(response_template): + item = response_template.duplicate(DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_SIGNALS) + item.show() + else: + item = Button.new() + item.name = "Response%d" % get_child_count() + if not response.is_allowed: + item.name = String(item.name) + "Disallowed" + item.disabled = true + + # If the item has a response property then use that + if "response" in item: + item.response = response + # Otherwise assume we can just set the text + else: + item.text = response.text + + item.set_meta("response", response) + + add_child(item) + + _configure_focus() + + +func _ready() -> void: + visibility_changed.connect(func(): + if visible and get_menu_items().size() > 0: + get_menu_items()[0].grab_focus() + ) + + if is_instance_valid(response_template): + response_template.hide() + + +# This is deprecated. +func set_responses(next_responses: Array) -> void: + self.responses = next_responses + + +# Prepare the menu for keyboard and mouse navigation. +func _configure_focus() -> void: + var items = get_menu_items() + for i in items.size(): + var item: Control = items[i] + + item.focus_mode = Control.FOCUS_ALL + + item.focus_neighbor_left = item.get_path() + item.focus_neighbor_right = item.get_path() + + if i == 0: + item.focus_neighbor_top = item.get_path() + item.focus_previous = item.get_path() + else: + item.focus_neighbor_top = items[i - 1].get_path() + item.focus_previous = items[i - 1].get_path() + + if i == items.size() - 1: + item.focus_neighbor_bottom = item.get_path() + item.focus_next = item.get_path() + else: + item.focus_neighbor_bottom = items[i + 1].get_path() + item.focus_next = items[i + 1].get_path() + + item.mouse_entered.connect(_on_response_mouse_entered.bind(item)) + item.gui_input.connect(_on_response_gui_input.bind(item, item.get_meta("response"))) + + items[0].grab_focus() + + +## Get the selectable items in the menu. +func get_menu_items() -> Array: + var items: Array = [] + for child in get_children(): + if not child.visible: continue + if "Disallowed" in child.name: continue + items.append(child) + + return items + + +### Signals + + +func _on_response_mouse_entered(item: Control) -> void: + if "Disallowed" in item.name: return + + item.grab_focus() + + +func _on_response_gui_input(event: InputEvent, item: Control, response) -> void: + if "Disallowed" in item.name: return + + get_viewport().set_input_as_handled() + + if event is InputEventMouseButton and event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT: + response_selected.emit(response) + elif event.is_action_pressed(&"ui_accept" if next_action.is_empty() else next_action) and item in get_menu_items(): + response_selected.emit(response) diff --git a/addons/dialogue_manager/dialogue_resource.gd b/addons/dialogue_manager/dialogue_resource.gd new file mode 100644 index 0000000..a406560 --- /dev/null +++ b/addons/dialogue_manager/dialogue_resource.gd @@ -0,0 +1,42 @@ +@tool +@icon("./assets/icon.svg") + +## A collection of dialogue lines for use with [code]DialogueManager[/code]. +class_name DialogueResource extends Resource + + +const _DialogueManager = preload("./dialogue_manager.gd") + +## A list of state shortcuts +@export var using_states: PackedStringArray = [] + +## A map of titles and the lines they point to. +@export var titles: Dictionary = {} + +## A list of character names. +@export var character_names: PackedStringArray = [] + +## The first title in the file. +@export var first_title: String = "" + +## A map of the encoded lines of dialogue. +@export var lines: Dictionary = {} + +## raw version of the text +@export var raw_text: String + + +## Get the next printable line of dialogue, starting from a referenced line ([code]title[/code] can +## be a title string or a stringified line number). Runs any mutations along the way and then returns +## the first dialogue line encountered. +func get_next_dialogue_line(title: String, extra_game_states: Array = [], mutation_behaviour: _DialogueManager.MutationBehaviour = _DialogueManager.MutationBehaviour.Wait) -> DialogueLine: + return await Engine.get_singleton("DialogueManager").get_next_dialogue_line(self, title, extra_game_states, mutation_behaviour) + + +## Get the list of any titles found in the file. +func get_titles() -> PackedStringArray: + return titles.keys() + + +func _to_string() -> String: + return "<DialogueResource titles=\"%s\">" % [",".join(titles.keys())] diff --git a/addons/dialogue_manager/dialogue_response.gd b/addons/dialogue_manager/dialogue_response.gd new file mode 100644 index 0000000..92cec24 --- /dev/null +++ b/addons/dialogue_manager/dialogue_response.gd @@ -0,0 +1,62 @@ +## A response to a line of dialogue, usualy attached to a [code]DialogueLine[/code]. +class_name DialogueResponse extends RefCounted + + +const _DialogueConstants = preload("./constants.gd") + + +## The ID of this response +var id: String + +## The internal type of this dialogue object, always set to [code]TYPE_RESPONSE[/code]. +var type: String = _DialogueConstants.TYPE_RESPONSE + +## The next line ID to use if this response is selected by the player. +var next_id: String = "" + +## [code]true[/code] if the condition of this line was met. +var is_allowed: bool = true + +## A character (depending on the "characters in responses" behaviour setting). +var character: String = "" + +## A dictionary of varialbe replaces for the character name. Generally for internal use only. +var character_replacements: Array[Dictionary] = [] + +## The prompt for this response. +var text: String = "" + +## A dictionary of variable replaces for the text. Generally for internal use only. +var text_replacements: Array[Dictionary] = [] + +## Any #tags +var tags: PackedStringArray = [] + +## The key to use for translating the text. +var translation_key: String = "" + + +func _init(data: Dictionary = {}) -> void: + if data.size() > 0: + id = data.id + type = data.type + next_id = data.next_id + is_allowed = data.is_allowed + character = data.character + character_replacements = data.character_replacements + text = data.text + text_replacements = data.text_replacements + tags = data.tags + translation_key = data.translation_key + + +func _to_string() -> String: + return "<DialogueResponse text=\"%s\">" % text + + +func get_tag_value(tag_name: String) -> String: + var wrapped := "%s=" % tag_name + for t in tags: + if t.begins_with(wrapped): + return t.replace(wrapped, "").strip_edges() + return "" diff --git a/addons/dialogue_manager/editor_translation_parser_plugin.gd b/addons/dialogue_manager/editor_translation_parser_plugin.gd new file mode 100644 index 0000000..9d404e2 --- /dev/null +++ b/addons/dialogue_manager/editor_translation_parser_plugin.gd @@ -0,0 +1,43 @@ +extends EditorTranslationParserPlugin + + +const DialogueConstants = preload("./constants.gd") +const DialogueSettings = preload("./settings.gd") +const DialogueManagerParseResult = preload("./components/parse_result.gd") + + +func _parse_file(path: String, msgids: Array, msgids_context_plural: Array) -> void: + var file: FileAccess = FileAccess.open(path, FileAccess.READ) + var text: String = file.get_as_text() + + var data: DialogueManagerParseResult = DialogueManagerParser.parse_string(text, path) + var known_keys: PackedStringArray = PackedStringArray([]) + + # Add all character names if settings ask for it + if DialogueSettings.get_setting("export_characters_in_translation", true): + var character_names: PackedStringArray = data.character_names + for character_name in character_names: + if character_name in known_keys: continue + + known_keys.append(character_name) + + msgids_context_plural.append([character_name.replace('"', '\\"'), "dialogue", ""]) + + # Add all dialogue lines and responses + var dialogue: Dictionary = data.lines + for key in dialogue.keys(): + var line: Dictionary = dialogue.get(key) + + if not line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: continue + if line.translation_key in known_keys: continue + + known_keys.append(line.translation_key) + + if line.translation_key == "" or line.translation_key == line.text: + msgids_context_plural.append([line.text.replace('"', '\\"'), "", ""]) + else: + msgids_context_plural.append([line.text.replace('"', '\\"'), line.translation_key.replace('"', '\\"'), ""]) + + +func _get_recognized_extensions() -> PackedStringArray: + return ["dialogue"] diff --git a/addons/dialogue_manager/example_balloon/ExampleBalloon.cs b/addons/dialogue_manager/example_balloon/ExampleBalloon.cs new file mode 100644 index 0000000..a6574e0 --- /dev/null +++ b/addons/dialogue_manager/example_balloon/ExampleBalloon.cs @@ -0,0 +1,204 @@ +using Godot; +using Godot.Collections; + +namespace DialogueManagerRuntime +{ + public partial class ExampleBalloon : CanvasLayer + { + [Export] public string NextAction = "ui_accept"; + [Export] public string SkipAction = "ui_cancel"; + + + Control balloon; + RichTextLabel characterLabel; + RichTextLabel dialogueLabel; + VBoxContainer responsesMenu; + + Resource resource; + Array<Variant> temporaryGameStates = new Array<Variant>(); + bool isWaitingForInput = false; + bool willHideBalloon = false; + + DialogueLine dialogueLine; + DialogueLine DialogueLine + { + get => dialogueLine; + set + { + isWaitingForInput = false; + balloon.FocusMode = Control.FocusModeEnum.All; + balloon.GrabFocus(); + + if (value == null) + { + QueueFree(); + return; + } + + dialogueLine = value; + UpdateDialogue(); + } + } + + + public override void _Ready() + { + balloon = GetNode<Control>("%Balloon"); + characterLabel = GetNode<RichTextLabel>("%CharacterLabel"); + dialogueLabel = GetNode<RichTextLabel>("%DialogueLabel"); + responsesMenu = GetNode<VBoxContainer>("%ResponsesMenu"); + + balloon.Hide(); + + balloon.GuiInput += (@event) => + { + if ((bool)dialogueLabel.Get("is_typing")) + { + bool mouseWasClicked = @event is InputEventMouseButton && (@event as InputEventMouseButton).ButtonIndex == MouseButton.Left && @event.IsPressed(); + bool skipButtonWasPressed = @event.IsActionPressed(SkipAction); + if (mouseWasClicked || skipButtonWasPressed) + { + GetViewport().SetInputAsHandled(); + dialogueLabel.Call("skip_typing"); + return; + } + } + + if (!isWaitingForInput) return; + if (dialogueLine.Responses.Count > 0) return; + + GetViewport().SetInputAsHandled(); + + if (@event is InputEventMouseButton && @event.IsPressed() && (@event as InputEventMouseButton).ButtonIndex == MouseButton.Left) + { + Next(dialogueLine.NextId); + } + else if (@event.IsActionPressed(NextAction) && GetViewport().GuiGetFocusOwner() == balloon) + { + Next(dialogueLine.NextId); + } + }; + + if (string.IsNullOrEmpty((string)responsesMenu.Get("next_action"))) + { + responsesMenu.Set("next_action", NextAction); + } + responsesMenu.Connect("response_selected", Callable.From((DialogueResponse response) => + { + Next(response.NextId); + })); + + DialogueManager.Mutated += OnMutated; + } + + + public override void _ExitTree() + { + DialogueManager.Mutated -= OnMutated; + } + + + public override void _UnhandledInput(InputEvent @event) + { + // Only the balloon is allowed to handle input while it's showing + GetViewport().SetInputAsHandled(); + } + + + public async void Start(Resource dialogueResource, string title, Array<Variant> extraGameStates = null) + { + temporaryGameStates = extraGameStates ?? new Array<Variant>(); + isWaitingForInput = false; + resource = dialogueResource; + + DialogueLine = await DialogueManager.GetNextDialogueLine(resource, title, temporaryGameStates); + } + + + public async void Next(string nextId) + { + DialogueLine = await DialogueManager.GetNextDialogueLine(resource, nextId, temporaryGameStates); + } + + + #region Helpers + + + private async void UpdateDialogue() + { + if (!IsNodeReady()) + { + await ToSignal(this, SignalName.Ready); + } + + // Set up the character name + characterLabel.Visible = !string.IsNullOrEmpty(dialogueLine.Character); + characterLabel.Text = Tr(dialogueLine.Character, "dialogue"); + + // Set up the dialogue + dialogueLabel.Hide(); + dialogueLabel.Set("dialogue_line", dialogueLine); + + // Set up the responses + responsesMenu.Hide(); + responsesMenu.Set("responses", dialogueLine.Responses); + + // Type out the text + balloon.Show(); + willHideBalloon = false; + dialogueLabel.Show(); + if (!string.IsNullOrEmpty(dialogueLine.Text)) + { + dialogueLabel.Call("type_out"); + await ToSignal(dialogueLabel, "finished_typing"); + } + + // Wait for input + if (dialogueLine.Responses.Count > 0) + { + balloon.FocusMode = Control.FocusModeEnum.None; + responsesMenu.Show(); + } + else if (!string.IsNullOrEmpty(dialogueLine.Time)) + { + float time = 0f; + if (!float.TryParse(dialogueLine.Time, out time)) + { + time = dialogueLine.Text.Length * 0.02f; + } + await ToSignal(GetTree().CreateTimer(time), "timeout"); + Next(dialogueLine.NextId); + } + else + { + isWaitingForInput = true; + balloon.FocusMode = Control.FocusModeEnum.All; + balloon.GrabFocus(); + } + } + + + #endregion + + + #region signals + + + private void OnMutated(Dictionary _mutation) + { + isWaitingForInput = false; + willHideBalloon = true; + GetTree().CreateTimer(0.1f).Timeout += () => + { + if (willHideBalloon) + { + willHideBalloon = false; + balloon.Hide(); + } + }; + } + + + #endregion + } +} \ No newline at end of file diff --git a/addons/dialogue_manager/example_balloon/example_balloon.gd b/addons/dialogue_manager/example_balloon/example_balloon.gd new file mode 100644 index 0000000..875e52f --- /dev/null +++ b/addons/dialogue_manager/example_balloon/example_balloon.gd @@ -0,0 +1,141 @@ +extends CanvasLayer + +## 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" + +@onready var balloon: Control = %Balloon +@onready var character_label: RichTextLabel = %CharacterLabel +@onready var dialogue_label: DialogueLabel = %DialogueLabel +@onready var responses_menu: DialogueResponsesMenu = %ResponsesMenu + +## 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 + +## The current line +var dialogue_line: DialogueLine: + set(next_dialogue_line): + is_waiting_for_input = false + balloon.focus_mode = Control.FOCUS_ALL + balloon.grab_focus() + + # The dialogue has finished so close the balloon + if not next_dialogue_line: + queue_free() + return + + # If the node isn't ready yet then none of the labels will be ready yet either + if not is_node_ready(): + await ready + + dialogue_line = next_dialogue_line + + 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.set_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() + get: + return dialogue_line + + +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 + + +func _unhandled_input(_event: InputEvent) -> void: + # Only the balloon is allowed to handle input while it's showing + get_viewport().set_input_as_handled() + + +## 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) + + +## 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) + + +### Signals + + +func _on_mutated(_mutation: Dictionary) -> void: + is_waiting_for_input = false + will_hide_balloon = true + get_tree().create_timer(0.1).timeout.connect(func(): + if will_hide_balloon: + will_hide_balloon = false + balloon.hide() + ) + + +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 _on_responses_menu_response_selected(response: DialogueResponse) -> void: + next(response.next_id) diff --git a/addons/dialogue_manager/example_balloon/example_balloon.tscn b/addons/dialogue_manager/example_balloon/example_balloon.tscn new file mode 100644 index 0000000..6facc26 --- /dev/null +++ b/addons/dialogue_manager/example_balloon/example_balloon.tscn @@ -0,0 +1,149 @@ +[gd_scene load_steps=9 format=3 uid="uid://73jm5qjy52vq"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/example_balloon/example_balloon.gd" id="1_36de5"] +[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_a8ve6"] +[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_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="ExampleBalloon" type="CanvasLayer"] +layer = 100 +script = ExtResource("1_36de5") + +[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="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("2_a8ve6")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +text = "Dialogue..." + +[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" + +[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"] diff --git a/addons/dialogue_manager/example_balloon/small_example_balloon.tscn b/addons/dialogue_manager/example_balloon/small_example_balloon.tscn new file mode 100644 index 0000000..3011833 --- /dev/null +++ b/addons/dialogue_manager/example_balloon/small_example_balloon.tscn @@ -0,0 +1,173 @@ +[gd_scene load_steps=10 format=3 uid="uid://13s5spsk34qu"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/example_balloon/example_balloon.gd" id="1_s2gbs"] +[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_hfvdi"] +[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_menu.gd" id="3_1j1j0"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_235ry"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.345098, 0.345098, 0.345098, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ufjut"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.227451, 0.227451, 0.227451, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(1, 1, 1, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fcbqo"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_t6i7a"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uy0d5"] +bg_color = Color(0, 0, 0, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="Theme" id="Theme_qq3yp"] +default_font_size = 8 +Button/styles/disabled = SubResource("StyleBoxFlat_235ry") +Button/styles/focus = SubResource("StyleBoxFlat_ufjut") +Button/styles/hover = SubResource("StyleBoxFlat_fcbqo") +Button/styles/normal = SubResource("StyleBoxFlat_t6i7a") +MarginContainer/constants/margin_bottom = 4 +MarginContainer/constants/margin_left = 8 +MarginContainer/constants/margin_right = 8 +MarginContainer/constants/margin_top = 4 +Panel/styles/panel = SubResource("StyleBoxFlat_uy0d5") + +[node name="ExampleBalloon" type="CanvasLayer"] +layer = 100 +script = ExtResource("1_s2gbs") + +[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"] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 3.0 +offset_top = -62.0 +offset_right = -4.0 +offset_bottom = -4.0 +grow_horizontal = 2 +grow_vertical = 0 + +[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="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("2_hfvdi")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +text = "Dialogue..." +skip_pause_at_abbreviations = PackedStringArray("Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex") + +[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 = -124.0 +offset_top = -218.0 +offset_right = 125.0 +offset_bottom = -50.0 +grow_horizontal = 2 +grow_vertical = 0 + +[node name="ResponsesMenu" type="VBoxContainer" parent="Balloon/Responses"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 8 +theme_override_constants/separation = 2 +script = ExtResource("3_1j1j0") + +[node name="ResponseExample" type="Button" parent="Balloon/Responses/ResponsesMenu"] +layout_mode = 2 +text = "Response Example" + +[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"] diff --git a/addons/dialogue_manager/import_plugin.gd b/addons/dialogue_manager/import_plugin.gd new file mode 100644 index 0000000..3f0af15 --- /dev/null +++ b/addons/dialogue_manager/import_plugin.gd @@ -0,0 +1,113 @@ +@tool +extends EditorImportPlugin + + +signal compiled_resource(resource: Resource) + + +const DialogueResource = preload("./dialogue_resource.gd") +const DialogueManagerParseResult = preload("./components/parse_result.gd") + +const compiler_version = 11 + + +func _get_importer_name() -> String: + # NOTE: A change to this forces a re-import of all dialogue + return "dialogue_manager_compiler_%s" % compiler_version + + +func _get_visible_name() -> String: + return "Dialogue" + + +func _get_import_order() -> int: + return -1000 + + +func _get_priority() -> float: + return 1000.0 + + +func _get_resource_type(): + return "Resource" + + +func _get_recognized_extensions() -> PackedStringArray: + return PackedStringArray(["dialogue"]) + + +func _get_save_extension(): + return "tres" + + +func _get_preset_count() -> int: + return 0 + + +func _get_preset_name(preset_index: int) -> String: + return "Unknown" + + +func _get_import_options(path: String, preset_index: int) -> Array: + # When the options array is empty there is a misleading error on export + # that actually means nothing so let's just have an invisible option. + return [{ + name = "defaults", + default_value = true + }] + + +func _get_option_visibility(path: String, option_name: StringName, options: Dictionary) -> bool: + return false + + +func _import(source_file: String, save_path: String, options: Dictionary, platform_variants: Array[String], gen_files: Array[String]) -> Error: + var cache = Engine.get_meta("DialogueCache") + + # Get the raw file contents + if not FileAccess.file_exists(source_file): return ERR_FILE_NOT_FOUND + + var file: FileAccess = FileAccess.open(source_file, FileAccess.READ) + var raw_text: String = file.get_as_text() + + # Parse the text + var parser: DialogueManagerParser = DialogueManagerParser.new() + var err: Error = parser.parse(raw_text, source_file) + var data: DialogueManagerParseResult = parser.get_data() + var errors: Array[Dictionary] = parser.get_errors() + parser.free() + + if err != OK: + printerr("%d errors found in %s" % [errors.size(), source_file]) + cache.add_errors_to_file(source_file, errors) + return err + + # Get the current addon version + var config: ConfigFile = ConfigFile.new() + config.load("res://addons/dialogue_manager/plugin.cfg") + var version: String = config.get_value("plugin", "version") + + # Save the results to a resource + var resource: DialogueResource = DialogueResource.new() + resource.set_meta("dialogue_manager_version", version) + + resource.using_states = data.using_states + resource.titles = data.titles + resource.first_title = data.first_title + resource.character_names = data.character_names + resource.lines = data.lines + resource.raw_text = data.raw_text + + # Clear errors and possibly trigger any cascade recompiles + cache.add_file(source_file, data) + + err = ResourceSaver.save(resource, "%s.%s" % [save_path, _get_save_extension()]) + + compiled_resource.emit(resource) + + # Recompile any dependencies + var dependent_paths: PackedStringArray = cache.get_dependent_paths_for_reimport(source_file) + for path in dependent_paths: + append_import_external_resource(path) + + return err diff --git a/addons/dialogue_manager/l10n/en.mo b/addons/dialogue_manager/l10n/en.mo new file mode 100644 index 0000000000000000000000000000000000000000..2ab4fdfdac7d7f52d3d107052e417714a09b6bdc GIT binary patch literal 9770 zcmb7|e~=|tRmU654>HjZFn|zEZYJRF#>`8yQCViQEZLdeWZ3Kvc4m`+N~h;_&rE0D z>wa|io7u@YBoHBGiKz+{1qJ^S!Lm$QT1xy;VkL@2Sx~i>f5Z~8fI_eo3$c`xTG7w< z{&=t7>_B1HJMY`~++XLOd(OG{^jBVe*+(OuC!n8%mM)8;-v>YR3jTN=x;lz}6imQt z!2<jV@KNwJ;KxCJ(KGyA1O5^CdhiS2kAYtY)$ZTGSA$nF7*j-V0AB~*2;K<38T@hZ z0nc9tUrYIMQ2jmuYMkE&uLGY4CGQKM=KBxuX7H6v`Udb$Q0-2G*MnV;kAmv=Nnigg zC^^0e-T;0Bd=+>Zi;+C91=ar+Q2kDTny>3|2fT^$$3TtqhaNA2>i18e<i7lsPQL3w z$#)c#9^d85wJ$&E%by168a)SU9T!3A{~tlg_dSnS!BqKr5LPq;UI88f)qft;Iu?EX zsxNPXY)SNMzWgyzdj2g?<NT@Te+lFleT_d<9R0iJYf`P_I#B&?12yk4P<mJZC3gZ| z1#W<v?=evN`jD@G29%u7gBtIzJ$@UM-d@4rw}Ll-(&tG~dRqngMUU~P^?d|X|4)Oe ze-6}s{hcqr2pY<-qVb!+gB~9QHUE1-+1sy!lJip_B1FIA%g=$*%a=g4{|d;E(YHZ< zcCnK8Iu@;Vw}5h?Sy1E5fd)JeO3n@Njo?$D^zjFv`oG}o|J9eTf{95+H-eIT2Ba!l z1f}OSQ1<v3sC9n=)IR+lsD1l0Q2j50lJ_5c{dax+|AJcgwfw1mAE@@TpaJg%wZ0tG zygQ)w;lrTje+FcT=<}fT@@4RfmqpP(gO^kOE{(MRFM`s;%MnuTt^*YZZU(2o{h;Q* z6V!T6fLDSKfm+WRsP;pUp`%B@JHV$v`Tg^r|4nc|<(ELow~xWJA4kD`;2BW;H$6TH z{uJe>L9Oq3Q1ZP1PJ`bB?*gaTv|GS?K=rRc?ccA0Ocgx?N-uxu%U=f%Q~n=N?GI5Y zJ)ZH{1^Gpr{7Ek#@%S_-eSQ{{++PGG-`|6h@4rFm=~|3i<(om35Bc&*Q2ibPwT=OJ z7x*Z61pE_F`us0Y^Ipl|iodT1<-czMrT4diYIiRvJ3jBr?*?Tb>%P1N%3nSRs@;b@ z|C6Bh{WGBK;CDU$Sx|cT3sC+37L@$o@c1Gq`L8AzOOES7wYwR-4ZIDMK4Y*0Zh$Ai zr$O1nzkmn98(7qx;5$I^KL8#AKMOKN^c|3<(KW{DWya$=DE<E?DE)j6{8{iKsQy>r ztiq$9^m_r+I8T7ukKX`g&wmWcUOx{?FMkDUJ%0mgJzoZ;$8UN5e}Y=~OQ70cgYl{T z>%gA@Zv=l1JPH0h_&#ty_^ijTf{#<4!WnJ{p9D4k=RmeP`g8Ck_*L*>a0cVmd>{At z8BlioEU36~5tMvi^Y|T5_V5y@bzV&{Qhx(V54VGo^C-wKTIcW0;8URX_Y0t1H>mdC z^7uUvk)kVpI*MKf>XCg&X6@qzNRQPC_?QYjk2|n3XrJ`F4SGAI`91)xK@1;lLbApC zAnEWukRAi=KpT+OJb-FQ&wC;HLj|os;gJr{Ko3CggMJA*0O|Q4^eEI<!9Of3`Vr_M z=-rTXAD(-8xyu*s4opyb{uOBGdD~zH{Q~q>=ocY9=ONj)9_^L%xC+TW2^02_uQbp+ z^n~SH`ga%>ValFEggYB2<RkY$%g`)z3-lUD&pITZn1gPG-U7WJ3XlBmGAM=Q8+w+Y z%OTmwBaj~1sh&mXgne_iRq&2`TKn<r=(K<7dVC|;gB0Um4jqSPptI0Bp<|Hz=M?k~ zsDxyH3s3^x4^2aQI*@E%&rt_9)=c^L2R**aqd>kFLpih$+JfYl=b&GPM$htaWhJXR z-CkK|QM(W)z1}3FY}T?WUdek|J*p@NTb2_Kl4dP%>ttgzmfquJ)S+H0H{-l;qioep z){nYnv65H)*oiPv>ZEzyO{#RVO~;O(mfbqas;aE&PSUHgB;AVh{-CUyEDd}HOY<f# zi+C-m<D!gVG+EJv`gAzx<=v#o;(XMn#j~Sb+P2A?UKZF{f6#2j6D(<n$(nej92TQ- zooum_IP}hoZrLC7G9<_@463ZI5q4a;k@WKPhpJ(&DyI2xBv@X!-g%L-;zU~5J+P`S z>}J}f#Ko|`oK<_*)lHQbtD)}UVSf-eC7bHzn^47iwsol{dU=6K6lvUNy~*lG;(pHZ zi&bj~!sROIu4kjo3f1GSDl!Zxom9RPfA8%c7AQIEs!zgHt3|(M3$4oKvg~EaNL}rk zNs(GLvfe#}Znr3V<1Lur_xnlE<^<mx?;dq&IZ{ijM}|(zl|AgG)n;W_blbMjs+!#M zRz*3;s-!7L=FqB|w1rm1MpEU;^4L#?#d=Y0wsdNX6MLt)P<N|*5Y`rN=FM8XJj{D( zWW!F}%j>4YYlCgBW`)GcU}8^sT1Vc+R;rR{Qg1|gQD;@-p_ABk)5>x?$q=JW(v76( zW`URHNv~YRhkP3;bT?1-9_lNsn7JgtXk5>0vJ0b`@#{g!tf5=ImaJ#-@^ZIKM?50o zpvP)P<2XO^f;3wL8P^~gjz{sldXQny-L<5^lYH|{1zkUWA(JQ~_OKwzXGs-TSr@za zf!y+mjF&Q1W4pzPZ5vg?qRIPNC#kB0SgYU>m%~QmFDug3qZT&E#c9?gd2f=rt4$r( zS>_v#t3oJgg~TxTWIzerUbfN@;@Pb_e<X{$Nult&tb<2xt{72{<mhM3TAA9g)a8t` zMj8fc)w$puDq3epi^ay4!wUNeyg?;j;XoLN|4=1ClHOhwrDoOkZfaXLtCHXvdU>~r zHLP{PaYa2GxYI6n8{%Yd^&B@yb8GuawMER;>i2B*o+0*E6*?|`D|dMJdfrxS5lbTo z(y&(4mz!C3c*nrHYn^`5bl2DithII=LT?k^Ip{X>a#)9Qm0|j5(Kq!)djZ+SQa}jJ znsRlOgLbmBJqNAt)mhV^R88VutjG7tBpq|wYr$`89FWzwx^#zigM;Ii4WWsEGw#cF zmQ@yqQ>o^N&D;sx>d*P!8>U&jf+JvsArQ1$g#H-z_u<CahE(TQQDmFQ<ATMQYp-9U zHs}{C)c&N|N;2&6y2lEv$n~z_Ju@85qai(?`&-p?hfPb?%_<qh9Br#U4%#c8x4npN z2$IB-S|L2Lf{bFS4RZBFSZ~@JF&w0*wUcb1KkKNTk#dx1D`QuVcCp#_z;c=orM!+u zV_8!P1BC_!!L(+dteyB#DP>r)T$k`XW@>&yO*iXtMl}tG`($0YzBivB@i4cL(7GOW zyIh2#vyMHpkj~tXcVURLX5Jr2=2TK}Q>v!Uo|!p^^Qd-a9@Wg6sr!<;nOX8$D=W(> zR);j7S;~@rt2}GcZ0gj)spI1b?&#b;HRmqHGfP_o#*_2hhCk-TVI%**0*;(tIx%x- z+)i_mG|U|5_L`#WS#xMPZ>G-nhE>v=IZ;;qde#&JTda>9JZ#+Sk^P0a>4>@Gz~QL} zXYO&Qx8yxrX57-vot=Z7gHzF*%|z_KQ3~STZ0=#~B_Nt3>9DWHTK%H34gHy<?sPiQ zA}NN+3v&W<TXZRgt#wCaZJN^T+g8t=eMh5tpJ23GMDt25)ExnAVqrpJ(TVOhqol&< z+&9)@Oj0nVF4|e@*vps@Vl<s-X)UkK!o1->3|AI(a7)q{ooGHJB7P=QBpkGK&8n>3 zF)`L-jN+ha){-VPR7z4Cckr3z%-FP~;}*e8#-3(jz=T0v9wI$)_SB;VTD^9n1(%m# zU}k&>ccSB?97RI;V_L24)xXu0`6^@6k#TJ+5t(FOK(1Z#uOgRSV`AK`wB5v%MQ=;n z!1V$}_6D5%!+uufU2CxJa6-YU?^|o#$g7*1<Q|j+RLoYEVE4^QZ#CPAPG(zXdYf>( zGi_R$JFZOApzv+&*v_qHyIb~#{bFa<Z2Mrj6P<DyjPc2U@fnPt-<k{a`;f1>7v|dw z({${eOKa4L>D+#k&mfFlGd9*C9Bk3hS+v_gt;I|qd8;{odVabSogbw-ctuEcCfGj7 zndG_jW`cLgT3SP+g0h%wU6Rb~;`lUXf=dE3QRb#?%9WM{P1J^@Wr7(Dqa{zcB~7$* zDar&ZBqw6pJjB#nSQCaA%H9~>Sq{ybLd)1)wz%;bm!@=xF&9vO*0<Ki3*J<1nPe5i z>_qCU=pZ{=p<y`n!eGl8UXmFGl;aw1c6zVOs`Y*150@+-@_e++Tx?mGucHO~al(~D zWK-f}<`(Z)6kKq*&)q)hxtnaqgls3AD$#MY9;AxiF8837U3zrRrZ#r`Iuz`^>Rd=> z7L~=AW5?!{#Vn1|mnHjkgtJ5*<`NcPu$hWC+UNmk)py>uxx|hPV7n=sq_;!V=h|po zQsQ-Rx|}SZQAWc`h1kB%23Ac{Vn*W)8;$9b6TR7sGTv=*2RFG-5!`un+mE$#cH41s zlAfKgV}u*KLqTWuuyh;!!#6jJS!T`*n*q`(Ou96QAT_-`j<p0IB837%qBxqTE!RL& zYmPg6$1272@r9q&jte`}(S4*!tc{JY^E8|Exz_m+5+@8og1LO4EmTOIjH@ChGgG;& ziw(2v)nnW+DYmSU8+WNR`?uZ8&H*}VAMMvfX4@6^B1~YU`jC4Wu2UN<C6$~Z|7uGb zcoOmZ&#c}dMZ^Ev132~%?j9|MEY2v4Gd7DGhm&z&n&VC*&j=cdb<#7N70w%IUKjfs zGfLk&(GTj>-s}Hg$8o-gt?io8-KTmz?|b2T<T5{d>97|mA8c&3j<+`RlyX2!iX8B? zlE1Sd>pSPuJ&*R57v6Q~&qkreqRkzxm)O{|7;-wonZ2QNAt4_bANyW1JfM|E_%+Pg zTn?A5(XDbhv%e1u$KsQ4YK|dj2#ia#SyYn)(c*eOFeT~K=-9Tl>Ml1SF6@`160A7< z7%EE-5QuEz2h)A}soizPWh3J&WF0MW!E8ojx20A_$l>khh!$4tNuj&jP+uCY^Kj+4 zq>DX<2uJpYqkB(QD0NDafc;#{dILMq3PIQUgWoq@HgpszkjWU5l!Xv|5JRWJR>pyS zI@=sOpd3}pVo;mqxfO=g)P~0BY(l<H!a_ExL3}pa+Jh+1I)<~V;rqRU(X{+%QMq)d z<}D7+J8fkn8uwD}aqJo&!p!t!6RC)ER3G+a915Ue>GmG2)!BnKBYBZHdBbJUeX+?| zih`mGQf{~Swk2&?J(hMtb#OOxE21IQ@Y(PKB*8{Wus<;u-N%_r61a$t=z?o4s<cOz zY;B}eUD$Q%+cQ|k(fTN{v5gv)`0bcc4oj-y5@F*~&runnbvC*LViPM$v{KBVZ$irJ z>;r3ZId<fePV**i_OuTvw>zW!G&gBPjifm5Qy&z`UDTz_?y|#INDlFyZbqZg&uN2w lCarTVtC5u*F#70OVIy|S{K&hD!7oD^?9RqbGge6_`aihw)SUnT literal 0 HcmV?d00001 diff --git a/addons/dialogue_manager/l10n/en.po b/addons/dialogue_manager/l10n/en.po new file mode 100644 index 0000000..bf844cb --- /dev/null +++ b/addons/dialogue_manager/l10n/en.po @@ -0,0 +1,481 @@ +msgid "" +msgstr "" +"Project-Id-Version: Dialogue Manager\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.2.2\n" + +msgid "start_a_new_file" +msgstr "Start a new file" + +msgid "open_a_file" +msgstr "Open a file" + +msgid "open.open" +msgstr "Open..." + +msgid "open.no_recent_files" +msgstr "No recent files" + +msgid "open.clear_recent_files" +msgstr "Clear recent files" + +msgid "save_all_files" +msgstr "Save all files" + +msgid "find_in_files" +msgstr "Find in files..." + +msgid "test_dialogue" +msgstr "Test dialogue" + +msgid "search_for_text" +msgstr "Search for text" + +msgid "insert" +msgstr "Insert" + +msgid "translations" +msgstr "Translations" + +msgid "settings" +msgstr "Settings" + +msgid "sponsor" +msgstr "Sponsor" + +msgid "show_support" +msgstr "Support Dialogue Manager" + +msgid "docs" +msgstr "Docs" + +msgid "insert.wave_bbcode" +msgstr "Wave BBCode" + +msgid "insert.shake_bbcode" +msgstr "Shake BBCode" + +msgid "insert.typing_pause" +msgstr "Typing pause" + +msgid "insert.typing_speed_change" +msgstr "Typing speed change" + +msgid "insert.auto_advance" +msgstr "Auto advance" + +msgid "insert.templates" +msgstr "Templates" + +msgid "insert.title" +msgstr "Title" + +msgid "insert.dialogue" +msgstr "Dialogue" + +msgid "insert.response" +msgstr "Response" + +msgid "insert.random_lines" +msgstr "Random lines" + +msgid "insert.random_text" +msgstr "Random text" + +msgid "insert.actions" +msgstr "Actions" + +msgid "insert.jump" +msgstr "Jump to title" + +msgid "insert.end_dialogue" +msgstr "End dialogue" + +msgid "generate_line_ids" +msgstr "Generate line IDs" + +msgid "save_characters_to_csv" +msgstr "Save character names to CSV..." + +msgid "save_to_csv" +msgstr "Save lines to CSV..." + +msgid "import_from_csv" +msgstr "Import line changes from CSV..." + +msgid "confirm_close" +msgstr "Save changes to '{path}'?" + +msgid "confirm_close.save" +msgstr "Save changes" + +msgid "confirm_close.discard" +msgstr "Discard" + +msgid "buffer.save" +msgstr "Save" + +msgid "buffer.save_as" +msgstr "Save as..." + +msgid "buffer.close" +msgstr "Close" + +msgid "buffer.close_all" +msgstr "Close all" + +msgid "buffer.close_other_files" +msgstr "Close other files" + +msgid "buffer.copy_file_path" +msgstr "Copy file path" + +msgid "buffer.show_in_filesystem" +msgstr "Show in FileSystem" + +msgid "settings.invalid_test_scene" +msgstr "\"{path}\" does not extend BaseDialogueTestScene." + +msgid "settings.revert_to_default_test_scene" +msgstr "Revert to default test scene" + +msgid "settings.default_balloon_hint" +msgstr "Custom balloon to use when calling \"DialogueManager.show_balloon()\"" + +msgid "settings.revert_to_default_balloon" +msgstr "Revert to default balloon" + +msgid "settings.default_balloon_path" +msgstr "<example balloon>" + +msgid "settings.autoload" +msgstr "Autoload" + +msgid "settings.path" +msgstr "Path" + +msgid "settings.new_template" +msgstr "New dialogue files will start with template text" + +msgid "settings.missing_keys" +msgstr "Treat missing translation keys as errors" + +msgid "settings.missing_keys_hint" +msgstr "If you are using static translation keys then having this enabled will help you find any lines that you haven't added a key to yet." + +msgid "settings.characters_translations" +msgstr "Export character names in translation files" + +msgid "settings.wrap_long_lines" +msgstr "Wrap long lines" + +msgid "settings.include_failed_responses" +msgstr "Include responses with failed conditions" + +msgid "settings.ignore_missing_state_values" +msgstr "Skip over missing state value errors (not recommended)" + +msgid "settings.custom_test_scene" +msgstr "Custom test scene (must extend BaseDialogueTestScene)" + +msgid "settings.default_csv_locale" +msgstr "Default CSV Locale" + +msgid "settings.states_shortcuts" +msgstr "State Shortcuts" + +msgid "settings.states_message" +msgstr "If an autoload is enabled here you can refer to its properties and methods without having to use its name." + +msgid "settings.states_hint" +msgstr "ie. Instead of \"SomeState.some_property\" you could just use \"some_property\"" + +msgid "settings.recompile_warning" +msgstr "Changing these settings will force a recompile of all dialogue. Only change them if you know what you are doing." + +msgid "settings.create_lines_for_responses_with_characters" +msgstr "Create child dialogue line for responses with character names in them" + +msgid "settings.open_in_external_editor" +msgstr "Open dialogue files in external editor" + +msgid "settings.external_editor_warning" +msgstr "Note: Syntax highlighting and detailed error checking are not supported in external editors." + +msgid "settings.include_characters_in_translations" +msgstr "Include character names in translation exports" + +msgid "settings.include_notes_in_translations" +msgstr "Include notes (## comments) in translation exports" + +msgid "settings.check_for_updates" +msgstr "Check for updates" + +msgid "n_of_n" +msgstr "{index} of {total}" + +msgid "search.find" +msgstr "Find:" + +msgid "search.find_all" +msgstr "Find all..." + +msgid "search.placeholder" +msgstr "Text to search for" + +msgid "search.replace_placeholder" +msgstr "Text to replace it with" + +msgid "search.replace_selected" +msgstr "Replace selected" + +msgid "search.previous" +msgstr "Previous" + +msgid "search.next" +msgstr "Next" + +msgid "search.match_case" +msgstr "Match case" + +msgid "search.toggle_replace" +msgstr "Replace" + +msgid "search.replace_with" +msgstr "Replace with:" + +msgid "search.replace" +msgstr "Replace" + +msgid "search.replace_all" +msgstr "Replace all" + +msgid "files_list.filter" +msgstr "Filter files" + +msgid "titles_list.filter" +msgstr "Filter titles" + +msgid "errors.key_not_found" +msgstr "Key \"{key}\" not found." + +msgid "errors.line_and_message" +msgstr "Error at {line}, {column}: {message}" + +msgid "errors_in_script" +msgstr "You have errors in your script. Fix them and then try again." + +msgid "errors_with_build" +msgstr "You need to fix dialogue errors before you can run your game." + +msgid "errors.import_errors" +msgstr "There are errors in this imported file." + +msgid "errors.already_imported" +msgstr "File already imported." + +msgid "errors.duplicate_import" +msgstr "Duplicate import name." + +msgid "errors.unknown_using" +msgstr "Unknown autoload in using statement." + +msgid "errors.empty_title" +msgstr "Titles cannot be empty." + +msgid "errors.duplicate_title" +msgstr "There is already a title with that name." + +msgid "errors.nested_title" +msgstr "Titles cannot be indented." + +msgid "errors.invalid_title_string" +msgstr "Titles can only contain alphanumeric characters and numbers." + +msgid "errors.invalid_title_number" +msgstr "Titles cannot begin with a number." + +msgid "errors.unknown_title" +msgstr "Unknown title." + +msgid "errors.jump_to_invalid_title" +msgstr "This jump is pointing to an invalid title." + +msgid "errors.title_has_no_content" +msgstr "That title has no content. Maybe change this to a \"=> END\"." + +msgid "errors.invalid_expression" +msgstr "Expression is invalid." + +msgid "errors.unexpected_condition" +msgstr "Unexpected condition." + +msgid "errors.duplicate_id" +msgstr "This ID is already on another line." + +msgid "errors.missing_id" +msgstr "This line is missing an ID." + +msgid "errors.invalid_indentation" +msgstr "Invalid indentation." + +msgid "errors.condition_has_no_content" +msgstr "A condition line needs an indented line below it." + +msgid "errors.incomplete_expression" +msgstr "Incomplete expression." + +msgid "errors.invalid_expression_for_value" +msgstr "Invalid expression for value." + +msgid "errors.file_not_found" +msgstr "File not found." + +msgid "errors.unexpected_end_of_expression" +msgstr "Unexpected end of expression." + +msgid "errors.unexpected_function" +msgstr "Unexpected function." + +msgid "errors.unexpected_bracket" +msgstr "Unexpected bracket." + +msgid "errors.unexpected_closing_bracket" +msgstr "Unexpected closing bracket." + +msgid "errors.missing_closing_bracket" +msgstr "Missing closing bracket." + +msgid "errors.unexpected_operator" +msgstr "Unexpected operator." + +msgid "errors.unexpected_comma" +msgstr "Unexpected comma." + +msgid "errors.unexpected_colon" +msgstr "Unexpected colon." + +msgid "errors.unexpected_dot" +msgstr "Unexpected dot." + +msgid "errors.unexpected_boolean" +msgstr "Unexpected boolean." + +msgid "errors.unexpected_string" +msgstr "Unexpected string." + +msgid "errors.unexpected_number" +msgstr "Unexpected number." + +msgid "errors.unexpected_variable" +msgstr "Unexpected variable." + +msgid "errors.invalid_index" +msgstr "Invalid index." + +msgid "errors.unexpected_assignment" +msgstr "Unexpected assignment." + +msgid "errors.unknown" +msgstr "Unknown syntax." + +msgid "update.available" +msgstr "v{version} available" + +msgid "update.is_available_for_download" +msgstr "Version %s is available for download!" + +msgid "update.downloading" +msgstr "Downloading..." + +msgid "update.download_update" +msgstr "Download update" + +msgid "update.needs_reload" +msgstr "The project needs to be reloaded to install the update." + +msgid "update.reload_ok_button" +msgstr "Reload project" + +msgid "update.reload_cancel_button" +msgstr "Do it later" + +msgid "update.reload_project" +msgstr "Reload project" + +msgid "update.release_notes" +msgstr "Read release notes" + +msgid "update.success" +msgstr "Dialogue Manager is now v{version}." + +msgid "update.failed" +msgstr "There was a problem downloading the update." + +msgid "runtime.no_resource" +msgstr "No dialogue resource provided." + +msgid "runtime.no_content" +msgstr "\"{file_path}\" has no content." + +msgid "runtime.errors" +msgstr "You have {count} errors in your dialogue text." + +msgid "runtime.error_detail" +msgstr "Line {line}: {message}" + +msgid "runtime.errors_see_details" +msgstr "You have {count} errors in your dialogue text. See Output for details." + +msgid "runtime.invalid_expression" +msgstr "\"{expression}\" is not a valid expression: {error}" + +msgid "runtime.array_index_out_of_bounds" +msgstr "Index {index} out of bounds of array \"{array}\"." + +msgid "runtime.left_hand_size_cannot_be_assigned_to" +msgstr "Left hand side of expression cannot be assigned to." + +msgid "runtime.key_not_found" +msgstr "Key \"{key}\" not found in dictionary \"{dictionary}\"" + +msgid "runtime.property_not_found" +msgstr "\"{property}\" is not a property on any game states ({states})." + +msgid "runtime.property_not_found_missing_export" +msgstr "\"{property}\" is not a property on any game states ({states}). You might need to add an [Export] decorator." + +msgid "runtime.method_not_found" +msgstr "\"{method}\" is not a method on any game states ({states})" + +msgid "runtime.signal_not_found" +msgstr "\"{signal_name}\" is not a signal on any game states ({states})" + +msgid "runtime.method_not_callable" +msgstr "\"{method}\" is not a callable method on \"{object}\"" + +msgid "runtime.unknown_operator" +msgstr "Unknown operator." + +msgid "runtime.unknown_autoload" +msgstr "\"{autoload}\" doesn't appear to be a valid autoload." + +msgid "runtime.something_went_wrong" +msgstr "Something went wrong." + +msgid "runtime.expected_n_got_n_args" +msgstr "\"{method}\" was called with {received} arguments but it only has {expected}." + +msgid "runtime.unsupported_array_type" +msgstr "Array[{type}] isn't supported in mutations. Use Array as a type instead." + +msgid "runtime.dialogue_balloon_missing_start_method" +msgstr "Your dialogue balloon is missing a \"start\" or \"Start\" method." \ No newline at end of file diff --git a/addons/dialogue_manager/l10n/es.po b/addons/dialogue_manager/l10n/es.po new file mode 100644 index 0000000..3cbaa32 --- /dev/null +++ b/addons/dialogue_manager/l10n/es.po @@ -0,0 +1,457 @@ +# +msgid "" +msgstr "" +"Project-Id-Version: Dialogue Manager\n" +"POT-Creation-Date: 2024-02-25 20:58\n" +"PO-Revision-Date: 2024-02-25 20:58\n" +"Last-Translator: you <you@example.com>\n" +"Language-Team: Spanish <yourteam@example.com>\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "start_a_new_file" +msgstr "Crear un nuevo archivo" + +msgid "open_a_file" +msgstr "Abrir un archivo" + +msgid "open.open" +msgstr "Abrir..." + +msgid "open.no_recent_files" +msgstr "No hay archivos recientes" + +msgid "open.clear_recent_files" +msgstr "Limpiar archivos recientes" + +msgid "save_all_files" +msgstr "Guardar todos los archivos" + +msgid "test_dialogue" +msgstr "Diálogo de prueba" + +msgid "search_for_text" +msgstr "Buscar texto" + +msgid "insert" +msgstr "Insertar" + +msgid "translations" +msgstr "Traducciones" + +msgid "settings" +msgstr "Ajustes" + +msgid "show_support" +msgstr "Contribuye con Dialogue Manager" + +msgid "docs" +msgstr "Docs" + +msgid "insert.wave_bbcode" +msgstr "BBCode ondulado" + +msgid "insert.shake_bbcode" +msgstr "BBCode agitado" + +msgid "insert.typing_pause" +msgstr "Pausa de escritura" + +msgid "insert.typing_speed_change" +msgstr "Cambiar la velocidad de escritura" + +msgid "insert.auto_advance" +msgstr "Avance automático" + +msgid "insert.templates" +msgstr "Plantillas" + +msgid "insert.title" +msgstr "Título" + +msgid "insert.dialogue" +msgstr "Diálogo" + +msgid "insert.response" +msgstr "Respuesta" + +msgid "insert.random_lines" +msgstr "Líneas aleatorias" + +msgid "insert.random_text" +msgstr "Texto aleatorio" + +msgid "insert.actions" +msgstr "Acciones" + +msgid "insert.jump" +msgstr "Ir al título" + +msgid "insert.end_dialogue" +msgstr "Finalizar diálogo" + +msgid "generate_line_ids" +msgstr "Generar IDs de línea" + +msgid "save_characters_to_csv" +msgstr "Guardar los nombres de los personajes en un archivo CSV..." + +msgid "save_to_csv" +msgstr "Guardar líneas en CSV..." + +msgid "import_from_csv" +msgstr "Importar cambios de línea desde CSV..." + +msgid "confirm_close" +msgstr "¿Guardar los cambios en '{path}'?" + +msgid "confirm_close.save" +msgstr "Guardar cambios" + +msgid "confirm_close.discard" +msgstr "Descartar" + +msgid "buffer.save" +msgstr "Guardar" + +msgid "buffer.save_as" +msgstr "Guardar como..." + +msgid "buffer.close" +msgstr "Cerrar" + +msgid "buffer.close_all" +msgstr "Cerrar todo" + +msgid "buffer.close_other_files" +msgstr "Cerrar otros archivos" + +msgid "buffer.copy_file_path" +msgstr "Copiar la ruta del archivo" + +msgid "buffer.show_in_filesystem" +msgstr "Mostrar en el sistema de archivos" + +msgid "settings.invalid_test_scene" +msgstr "\"{path}\" no extiende BaseDialogueTestScene." + +msgid "settings.revert_to_default_test_scene" +msgstr "Revertir a la escena de prueba por defecto" + +msgid "settings.default_balloon_hint" +msgstr "" +"Globo personalizado para usar al llamar a \"DialogueManager.show_balloon()\"" + +msgid "settings.revert_to_default_balloon" +msgstr "Volver al globo predeterminado" + +msgid "settings.default_balloon_path" +msgstr "<globo de ejemplo>" + +msgid "settings.autoload" +msgstr "Autocarga" + +msgid "settings.path" +msgstr "Ruta" + +msgid "settings.new_template" +msgstr "Los nuevos archivos de diálogo empezarán con una plantilla" + +msgid "settings.missing_keys" +msgstr "Tratar las claves de traducción faltantes como errores" + +msgid "settings.missing_keys_hint" +msgstr "Si estás utilizando claves de traducción estáticas, tener esta opción habilitada te ayudará a encontrar cualquier línea a la que aún no le hayas añadido una clave." + +msgid "settings.characters_translations" +msgstr "Exportar nombres de personajes en archivos de traducción" + +msgid "settings.wrap_long_lines" +msgstr "Romper líneas largas" + +msgid "settings.include_failed_responses" +msgstr "Incluir respuestas con condiciones fallidas" + +msgid "settings.ignore_missing_state_values" +msgstr "Omitir errores de valores de estado faltantes (no recomendado)" + +msgid "settings.custom_test_scene" +msgstr "Escena de prueba personalizada (debe extender BaseDialogueTestScene)" + +msgid "settings.default_csv_locale" +msgstr "Localización CSV por defecto" + +msgid "settings.states_shortcuts" +msgstr "Atajos de teclado" + +msgid "settings.states_message" +msgstr "Si un autoload está habilitado aquí, puedes referirte a sus propiedades y métodos sin tener que usar su nombre." + +msgid "settings.states_hint" +msgstr "ie. En lugar de \"SomeState.some_property\" podría simplemente usar \"some_property\"" + +msgid "settings.recompile_warning" +msgstr "Cambiar estos ajustes obligará a recompilar todo el diálogo. Hazlo solo si sabes lo que estás haciendo." + +msgid "settings.create_lines_for_responses_with_characters" +msgstr "Crear línea de diálogo para respuestas con nombres de personajes dentro." + +msgid "settings.open_in_external_editor" +msgstr "Abrir archivos de diálogo en el editor externo" + +msgid "settings.external_editor_warning" +msgstr "Nota: El resaltado de sintaxis y la verificación detallada de errores no están soportados en editores externos." + +msgid "settings.include_characters_in_translations" +msgstr "Incluir nombres de personajes en las exportaciones de traducción" + +msgid "settings.include_notes_in_translations" +msgstr "Incluir notas (## comentarios) en las exportaciones de traducción" + +msgid "n_of_n" +msgstr "{index} de {total}" + +msgid "search.previous" +msgstr "Anterior" + +msgid "search.next" +msgstr "Siguiente" + +msgid "search.match_case" +msgstr "Coincidir mayúsculas/minúsculas" + +msgid "search.toggle_replace" +msgstr "Reemplazar" + +msgid "search.replace_with" +msgstr "Reemplazar con:" + +msgid "search.replace" +msgstr "Reemplazar" + +msgid "search.replace_all" +msgstr "Reemplazar todo" + +msgid "files_list.filter" +msgstr "Filtrar archivos" + +msgid "titles_list.filter" +msgstr "Filtrar títulos" + +msgid "errors.key_not_found" +msgstr "La tecla \"{key}\" no se encuentra." + +msgid "errors.line_and_message" +msgstr "Error en {line}, {column}: {message}" + +msgid "errors_in_script" +msgstr "Tienes errores en tu guion. Corrígelos y luego inténtalo de nuevo." + +msgid "errors_with_build" +msgstr "Debes corregir los errores de diálogo antes de poder ejecutar tu juego." + +msgid "errors.import_errors" +msgstr "Hay errores en este archivo importado." + +msgid "errors.already_imported" +msgstr "Archivo ya importado." + +msgid "errors.duplicate_import" +msgstr "Nombre de importación duplicado." + +msgid "errors.unknown_using" +msgstr "Autoload desconocida en la declaración de uso." + +msgid "errors.empty_title" +msgstr "Los títulos no pueden estar vacíos." + +msgid "errors.duplicate_title" +msgstr "Ya hay un título con ese nombre." + +msgid "errors.nested_title" +msgstr "Los títulos no pueden tener sangría." + +msgid "errors.invalid_title_string" +msgstr "Los títulos solo pueden contener caracteres alfanuméricos y números." + +msgid "errors.invalid_title_number" +msgstr "Los títulos no pueden empezar con un número." + +msgid "errors.unknown_title" +msgstr "Título desconocido." + +msgid "errors.jump_to_invalid_title" +msgstr "Este salto está apuntando a un título inválido." + +msgid "errors.title_has_no_content" +msgstr "Ese título no tiene contenido. Quizá cambiarlo a \"=> FIN\"." + +msgid "errors.invalid_expression" +msgstr "La expresión es inválida." + +msgid "errors.unexpected_condition" +msgstr "Condición inesperada." + +msgid "errors.duplicate_id" +msgstr "Este ID ya está en otra línea." + +msgid "errors.missing_id" +msgstr "Esta línea está sin ID." + +msgid "errors.invalid_indentation" +msgstr "Sangría no válida." + +msgid "errors.condition_has_no_content" +msgstr "Una línea de condición necesita una línea sangrada debajo de ella." + +msgid "errors.incomplete_expression" +msgstr "Expresión incompleta." + +msgid "errors.invalid_expression_for_value" +msgstr "Expresión no válida para valor." + +msgid "errors.file_not_found" +msgstr "Archivo no encontrado." + +msgid "errors.unexpected_end_of_expression" +msgstr "Fin de expresión inesperado." + +msgid "errors.unexpected_function" +msgstr "Función inesperada." + +msgid "errors.unexpected_bracket" +msgstr "Corchete inesperado." + +msgid "errors.unexpected_closing_bracket" +msgstr "Bracket de cierre inesperado." + +msgid "errors.missing_closing_bracket" +msgstr "Falta cerrar corchete." + +msgid "errors.unexpected_operator" +msgstr "Operador inesperado." + +msgid "errors.unexpected_comma" +msgstr "Coma inesperada." + +msgid "errors.unexpected_colon" +msgstr "Dos puntos inesperados" + +msgid "errors.unexpected_dot" +msgstr "Punto inesperado." + +msgid "errors.unexpected_boolean" +msgstr "Booleano inesperado." + +msgid "errors.unexpected_string" +msgstr "String inesperado." + +msgid "errors.unexpected_number" +msgstr "Número inesperado." + +msgid "errors.unexpected_variable" +msgstr "Variable inesperada." + +msgid "errors.invalid_index" +msgstr "Índice no válido." + +msgid "errors.unexpected_assignment" +msgstr "Asignación inesperada." + +msgid "errors.unknown" +msgstr "Sintaxis desconocida." + +msgid "update.available" +msgstr "v{version} disponible" + +msgid "update.is_available_for_download" +msgstr "¡La versión %s ya está disponible para su descarga!" + +msgid "update.downloading" +msgstr "Descargando..." + +msgid "update.download_update" +msgstr "Descargar actualización" + +msgid "update.needs_reload" +msgstr "El proyecto debe ser recargado para instalar la actualización." + +msgid "update.reload_ok_button" +msgstr "Recargar proyecto" + +msgid "update.reload_cancel_button" +msgstr "Hazlo más tarde" + +msgid "update.reload_project" +msgstr "Recargar proyecto" + +msgid "update.release_notes" +msgstr "Leer las notas de la versión" + +msgid "update.success" +msgstr "El Gestor de Diálogo ahora es v{versión}." + +msgid "update.failed" +msgstr "Hubo un problema al descargar la actualización." + +msgid "runtime.no_resource" +msgstr "Recurso de diálogo no proporcionado." + +msgid "runtime.no_content" +msgstr "\"{file_path}\" no tiene contenido." + +msgid "runtime.errors" +msgstr "Tienes {count} errores en tu diálogo de texto." + +msgid "runtime.error_detail" +msgstr "Línea {line}: {message}" + +msgid "runtime.errors_see_details" +msgstr "Tienes {count} errores en tu texto de diálogo. Consulta la salida para más detalles." + +msgid "runtime.invalid_expression" +msgstr "\"{expression}\" no es una expresión válida: {error}" + +msgid "runtime.array_index_out_of_bounds" +msgstr "Índice {index} fuera de los límites del array \"{array}\"." + +msgid "runtime.left_hand_size_cannot_be_assigned_to" +msgstr "El lado izquierdo de la expresión no se puede asignar." + +msgid "runtime.key_not_found" +msgstr "Clave \"{key}\" no encontrada en el diccionario \"{dictionary}\"" + +msgid "runtime.property_not_found" +msgstr "\"{property}\" no es una propiedad en ningún estado del juego ({states})." + +msgid "runtime.property_not_found_missing_export" +msgstr "\"{property}\" no es una propiedad en ningún estado del juego ({states}). Es posible que necesites añadir un decorador [Export]." + +msgid "runtime.method_not_found" +msgstr "\"{method}\" no es un método en ningún estado del juego ({states})" + +msgid "runtime.signal_not_found" +msgstr "\"{signal_name}\" no es una señal en ningún estado del juego ({states})" + +msgid "runtime.method_not_callable" +msgstr "\"{method}\" no es un método llamable en \"{object}\"" + +msgid "runtime.unknown_operator" +msgstr "Operador desconocido." + +msgid "runtime.unknown_autoload" +msgstr "\"{autoload}\" parece no ser un autoload válido." + +msgid "runtime.something_went_wrong" +msgstr "Algo salió mal." + +msgid "runtime.expected_n_got_n_args" +msgstr "El método \"{method}\" se llamó con {received} argumentos, pero solo tiene {expected}." + +msgid "runtime.unsupported_array_type" +msgstr "Array[{type}] no está soportado en mutaciones. Utiliza Array como tipo en su lugar." + +msgid "runtime.dialogue_balloon_missing_start_method" +msgstr "Tu globo de diálogo no tiene un método \"start\" o \"Start\"." diff --git a/addons/dialogue_manager/l10n/translations.pot b/addons/dialogue_manager/l10n/translations.pot new file mode 100644 index 0000000..4aeec3b --- /dev/null +++ b/addons/dialogue_manager/l10n/translations.pot @@ -0,0 +1,471 @@ +msgid "" +msgstr "" +"Project-Id-Version: Dialogue Manager\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8-bit\n" + +msgid "start_a_new_file" +msgstr "" + +msgid "open_a_file" +msgstr "" + +msgid "open.open" +msgstr "" + +msgid "open.no_recent_files" +msgstr "" + +msgid "open.clear_recent_files" +msgstr "" + +msgid "save_all_files" +msgstr "" + +msgid "find_in_files" +msgstr "" + +msgid "test_dialogue" +msgstr "" + +msgid "search_for_text" +msgstr "" + +msgid "insert" +msgstr "" + +msgid "translations" +msgstr "" + +msgid "settings" +msgstr "" + +msgid "sponsor" +msgstr "" + +msgid "show_support" +msgstr "" + +msgid "docs" +msgstr "" + +msgid "insert.wave_bbcode" +msgstr "" + +msgid "insert.shake_bbcode" +msgstr "" + +msgid "insert.typing_pause" +msgstr "" + +msgid "insert.typing_speed_change" +msgstr "" + +msgid "insert.auto_advance" +msgstr "" + +msgid "insert.templates" +msgstr "" + +msgid "insert.title" +msgstr "" + +msgid "insert.dialogue" +msgstr "" + +msgid "insert.response" +msgstr "" + +msgid "insert.random_lines" +msgstr "" + +msgid "insert.random_text" +msgstr "" + +msgid "insert.actions" +msgstr "" + +msgid "insert.jump" +msgstr "" + +msgid "insert.end_dialogue" +msgstr "" + +msgid "generate_line_ids" +msgstr "" + +msgid "save_to_csv" +msgstr "" + +msgid "import_from_csv" +msgstr "" + +msgid "confirm_close" +msgstr "" + +msgid "confirm_close.save" +msgstr "" + +msgid "confirm_close.discard" +msgstr "" + +msgid "buffer.save" +msgstr "" + +msgid "buffer.save_as" +msgstr "" + +msgid "buffer.close" +msgstr "" + +msgid "buffer.close_all" +msgstr "" + +msgid "buffer.close_other_files" +msgstr "" + +msgid "buffer.copy_file_path" +msgstr "" + +msgid "buffer.show_in_filesystem" +msgstr "" + +msgid "settings.invalid_test_scene" +msgstr "" + +msgid "settings.revert_to_default_test_scene" +msgstr "" + +msgid "settings.default_balloon_hint" +msgstr "" + +msgid "settings.revert_to_default_balloon" +msgstr "" + +msgid "settings.default_balloon_path" +msgstr "" + +msgid "settings.autoload" +msgstr "" + +msgid "settings.path" +msgstr "" + +msgid "settings.new_template" +msgstr "" + +msgid "settings.missing_keys" +msgstr "" + +msgid "settings.missing_keys_hint" +msgstr "" + +msgid "settings.characters_translations" +msgstr "" + +msgid "settings.wrap_long_lines" +msgstr "" + +msgid "settings.include_failed_responses" +msgstr "" + +msgid "settings.ignore_missing_state_values" +msgstr "" + +msgid "settings.custom_test_scene" +msgstr "" + +msgid "settings.default_csv_locale" +msgstr "" + +msgid "settings.states_shortcuts" +msgstr "" + +msgid "settings.states_message" +msgstr "" + +msgid "settings.states_hint" +msgstr "" + +msgid "settings.recompile_warning" +msgstr "" + +msgid "settings.create_lines_for_responses_with_characters" +msgstr "" + +msgid "settings.open_in_external_editor" +msgstr "" + +msgid "settings.external_editor_warning" +msgstr "" + +msgid "settings.include_characters_in_translations" +msgstr "" + +msgid "settings.include_notes_in_translations" +msgstr "" + +msgid "settings.check_for_updates" +msgstr "" + +msgid "n_of_n" +msgstr "" + +msgid "search.find" +msgstr "" + +msgid "search.find_all" +msgstr "" + +msgid "search.placeholder" +msgstr "" + +msgid "search.replace_placeholder" +msgstr "" + +msgid "search.replace_selected" +msgstr "" + +msgid "search.previous" +msgstr "" + +msgid "search.next" +msgstr "" + +msgid "search.match_case" +msgstr "" + +msgid "search.toggle_replace" +msgstr "" + +msgid "search.replace_with" +msgstr "" + +msgid "search.replace" +msgstr "" + +msgid "search.replace_all" +msgstr "" + +msgid "files_list.filter" +msgstr "" + +msgid "titles_list.filter" +msgstr "" + +msgid "errors.key_not_found" +msgstr "" + +msgid "errors.line_and_message" +msgstr "" + +msgid "errors_in_script" +msgstr "" + +msgid "errors_with_build" +msgstr "" + +msgid "errors.import_errors" +msgstr "" + +msgid "errors.already_imported" +msgstr "" + +msgid "errors.duplicate_import" +msgstr "" + +msgid "errors.unknown_using" +msgstr "" + +msgid "errors.empty_title" +msgstr "" + +msgid "errors.duplicate_title" +msgstr "" + +msgid "errors.nested_title" +msgstr "" + +msgid "errors.invalid_title_string" +msgstr "" + +msgid "errors.invalid_title_number" +msgstr "" + +msgid "errors.unknown_title" +msgstr "" + +msgid "errors.jump_to_invalid_title" +msgstr "" + +msgid "errors.title_has_no_content" +msgstr "" + +msgid "errors.invalid_expression" +msgstr "" + +msgid "errors.unexpected_condition" +msgstr "" + +msgid "errors.duplicate_id" +msgstr "" + +msgid "errors.missing_id" +msgstr "" + +msgid "errors.invalid_indentation" +msgstr "" + +msgid "errors.condition_has_no_content" +msgstr "" + +msgid "errors.incomplete_expression" +msgstr "" + +msgid "errors.invalid_expression_for_value" +msgstr "" + +msgid "errors.file_not_found" +msgstr "" + +msgid "errors.unexpected_end_of_expression" +msgstr "" + +msgid "errors.unexpected_function" +msgstr "" + +msgid "errors.unexpected_bracket" +msgstr "" + +msgid "errors.unexpected_closing_bracket" +msgstr "" + +msgid "errors.missing_closing_bracket" +msgstr "" + +msgid "errors.unexpected_operator" +msgstr "" + +msgid "errors.unexpected_comma" +msgstr "" + +msgid "errors.unexpected_colon" +msgstr "" + +msgid "errors.unexpected_dot" +msgstr "" + +msgid "errors.unexpected_boolean" +msgstr "" + +msgid "errors.unexpected_string" +msgstr "" + +msgid "errors.unexpected_number" +msgstr "" + +msgid "errors.unexpected_variable" +msgstr "" + +msgid "errors.invalid_index" +msgstr "" + +msgid "errors.unexpected_assignment" +msgstr "" + +msgid "errors.unknown" +msgstr "" + +msgid "update.available" +msgstr "" + +msgid "update.is_available_for_download" +msgstr "" + +msgid "update.downloading" +msgstr "" + +msgid "update.download_update" +msgstr "" + +msgid "update.needs_reload" +msgstr "" + +msgid "update.reload_ok_button" +msgstr "" + +msgid "update.reload_cancel_button" +msgstr "" + +msgid "update.reload_project" +msgstr "" + +msgid "update.release_notes" +msgstr "" + +msgid "update.success" +msgstr "" + +msgid "update.failed" +msgstr "" + +msgid "runtime.no_resource" +msgstr "" + +msgid "runtime.no_content" +msgstr "" + +msgid "runtime.errors" +msgstr "" + +msgid "runtime.error_detail" +msgstr "" + +msgid "runtime.errors_see_details" +msgstr "" + +msgid "runtime.invalid_expression" +msgstr "" + +msgid "runtime.array_index_out_of_bounds" +msgstr "" + +msgid "runtime.left_hand_size_cannot_be_assigned_to" +msgstr "" + +msgid "runtime.key_not_found" +msgstr "" + +msgid "runtime.property_not_found" +msgstr "" + +msgid "runtime.property_not_found_missing_export" +msgstr "" + +msgid "runtime.method_not_found" +msgstr "" + +msgid "runtime.signal_not_found" +msgstr "" + +msgid "runtime.method_not_callable" +msgstr "" + +msgid "runtime.unknown_operator" +msgstr "" + +msgid "runtime.unknown_autoload" +msgstr "" + +msgid "runtime.something_went_wrong" +msgstr "" + +msgid "runtime.expected_n_got_n_args" +msgstr "" + +msgid "runtime.unsupported_array_type" +msgstr "" + +msgid "runtime.dialogue_balloon_missing_start_method" +msgstr "" \ No newline at end of file diff --git a/addons/dialogue_manager/l10n/zh.po b/addons/dialogue_manager/l10n/zh.po new file mode 100644 index 0000000..b7f032f --- /dev/null +++ b/addons/dialogue_manager/l10n/zh.po @@ -0,0 +1,408 @@ +msgid "" +msgstr "" +"Project-Id-Version: Dialogue Manager\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: penghao123456、憨憨羊の宇航鸽鸽\n" +"Language: zh\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.4\n" + +msgid "start_a_new_file" +msgstr "创建新文件" + +msgid "open_a_file" +msgstr "打开已有文件" + +msgid "open.open" +msgstr "打开……" + +msgid "open.no_recent_files" +msgstr "无历史记录" + +msgid "open.clear_recent_files" +msgstr "清空历史记录" + +msgid "save_all_files" +msgstr "保存所有文件" + +msgid "test_dialogue" +msgstr "测试对话" + +msgid "search_for_text" +msgstr "查找……" + +msgid "insert" +msgstr "插入" + +msgid "translations" +msgstr "翻译" + +msgid "settings" +msgstr "设置" + +msgid "show_support" +msgstr "支持 Dialogue Manager" + +msgid "docs" +msgstr "文档" + +msgid "insert.wave_bbcode" +msgstr "BBCode [lb]wave[rb]" + +msgid "insert.shake_bbcode" +msgstr "BBCode [lb]wave[rb]" + +msgid "insert.typing_pause" +msgstr "输入间隔" + +msgid "insert.typing_speed_change" +msgstr "输入速度变更" + +msgid "insert.auto_advance" +msgstr "自动切行" + +msgid "insert.templates" +msgstr "模板" + +msgid "insert.title" +msgstr "标题" + +msgid "insert.dialogue" +msgstr "对话" + +msgid "insert.response" +msgstr "回复选项" + +msgid "insert.random_lines" +msgstr "随机行" + +msgid "insert.random_text" +msgstr "随机文本" + +msgid "insert.actions" +msgstr "操作" + +msgid "insert.jump" +msgstr "标题间跳转" + +msgid "insert.end_dialogue" +msgstr "结束对话" + +msgid "generate_line_ids" +msgstr "生成行 ID" + +msgid "save_to_csv" +msgstr "生成 CSV" + +msgid "import_from_csv" +msgstr "从 CSV 导入" + +msgid "confirm_close" +msgstr "是否要保存到“{path}”?" + +msgid "confirm_close.save" +msgstr "保存" + +msgid "confirm_close.discard" +msgstr "不保存" + +msgid "buffer.save" +msgstr "保存" + +msgid "buffer.save_as" +msgstr "另存为……" + +msgid "buffer.close" +msgstr "关闭" + +msgid "buffer.close_all" +msgstr "全部关闭" + +msgid "buffer.close_other_files" +msgstr "关闭其他文件" + +msgid "buffer.copy_file_path" +msgstr "复制文件路径" + +msgid "buffer.show_in_filesystem" +msgstr "在 Godot 侧边栏中显示" + +msgid "settings.revert_to_default_test_scene" +msgstr "重置测试场景设定" + +msgid "settings.autoload" +msgstr "Autoload" + +msgid "settings.path" +msgstr "路径" + +msgid "settings.new_template" +msgstr "新建文件时自动插入模板" + +msgid "settings.missing_keys" +msgstr "将翻译键缺失视为错误" + +msgid "settings.missing_keys_hint" +msgstr "如果你使用静态键,这将会帮助你寻找未添加至翻译文件的键。" + +msgid "settings.characters_translations" +msgstr "在翻译文件中导出角色名。" + +msgid "settings.wrap_long_lines" +msgstr "自动折行" + +msgid "settings.include_failed_responses" +msgstr "在判断条件失败时仍显示回复选项" + +msgid "settings.ignore_missing_state_values" +msgstr "忽略全局变量缺失错误(不建议)" + +msgid "settings.custom_test_scene" +msgstr "自定义测试场景(必须继承自BaseDialogueTestScene)" + +msgid "settings.default_csv_locale" +msgstr "默认 CSV 区域格式" + +msgid "settings.states_shortcuts" +msgstr "全局变量映射" + +msgid "settings.states_message" +msgstr "当一个 Autoload 在这里被勾选,他的所有成员会被映射为全局变量。" + +msgid "settings.states_hint" +msgstr "比如,当你开启对于“Foo”的映射时,你可以将“Foo.bar”简写成“bar”。" + +msgid "n_of_n" +msgstr "第{index}个,共{total}个" + +msgid "search.previous" +msgstr "查找上一个" + +msgid "search.next" +msgstr "查找下一个" + +msgid "search.match_case" +msgstr "大小写敏感" + +msgid "search.toggle_replace" +msgstr "替换" + +msgid "search.replace_with" +msgstr "替换为" + +msgid "search.replace" +msgstr "替换" + +msgid "search.replace_all" +msgstr "全部替换" + +msgid "files_list.filter" +msgstr "查找文件" + +msgid "titles_list.filter" +msgstr "查找标题" + +msgid "errors.key_not_found" +msgstr "键“{key}”未找到" + +msgid "errors.line_and_message" +msgstr "第{line}行第{colume}列发生错误:{message}" + +msgid "errors_in_script" +msgstr "你的脚本中存在错误。请修复错误,然后重试。" + +msgid "errors_with_build" +msgstr "请先解决 Dialogue 中的错误。" + +msgid "errors.import_errors" +msgstr "被导入的文件存在问题。" + +msgid "errors.already_imported" +msgstr "文件已被导入。" + +msgid "errors.duplicate_import" +msgstr "导入名不能重复。" + +msgid "errors.empty_title" +msgstr "标题名不能为空。" + +msgid "errors.duplicate_title" +msgstr "标题名不能重复。" + +msgid "errors.nested_title" +msgstr "标题不能嵌套。" + +msgid "errors.invalid_title_string" +msgstr "标题名无效。" + +msgid "errors.invalid_title_number" +msgstr "标题不能以数字开始。" + +msgid "errors.unknown_title" +msgstr "标题未定义。" + +msgid "errors.jump_to_invalid_title" +msgstr "标题名无效。" + +msgid "errors.title_has_no_content" +msgstr "目标标题为空。请替换为“=> END”。" + +msgid "errors.invalid_expression" +msgstr "表达式无效。" + +msgid "errors.unexpected_condition" +msgstr "未知条件。" + +msgid "errors.duplicate_id" +msgstr "ID 重复。" + +msgid "errors.missing_id" +msgstr "ID 不存在。" + +msgid "errors.invalid_indentation" +msgstr "缩进无效。" + +msgid "errors.condition_has_no_content" +msgstr "条件下方不能为空。" + +msgid "errors.incomplete_expression" +msgstr "不完整的表达式。" + +msgid "errors.invalid_expression_for_value" +msgstr "无效的赋值表达式。" + +msgid "errors.file_not_found" +msgstr "文件不存在。" + +msgid "errors.unexpected_end_of_expression" +msgstr "表达式 end 不应存在。" + +msgid "errors.unexpected_function" +msgstr "函数不应存在。" + +msgid "errors.unexpected_bracket" +msgstr "方括号不应存在。" + +msgid "errors.unexpected_closing_bracket" +msgstr "方括号不应存在。" + +msgid "errors.missing_closing_bracket" +msgstr "闭方括号不存在。" + +msgid "errors.unexpected_operator" +msgstr "操作符不应存在。" + +msgid "errors.unexpected_comma" +msgstr "逗号不应存在。" + +msgid "errors.unexpected_colon" +msgstr "冒号不应存在。" + +msgid "errors.unexpected_dot" +msgstr "句号不应存在。" + +msgid "errors.unexpected_boolean" +msgstr "布尔值不应存在。" + +msgid "errors.unexpected_string" +msgstr "字符串不应存在。" + +msgid "errors.unexpected_number" +msgstr "数字不应存在。" + +msgid "errors.unexpected_variable" +msgstr "标识符不应存在。" + +msgid "errors.invalid_index" +msgstr "索引无效。" + +msgid "errors.unexpected_assignment" +msgstr "不应在条件判断中使用 = ,应使用 == 。" + +msgid "errors.unknown" +msgstr "语法错误。" + +msgid "update.available" +msgstr "v{version} 更新可用。" + +msgid "update.is_available_for_download" +msgstr "v%s 已经可以下载。" + +msgid "update.downloading" +msgstr "正在下载更新……" + +msgid "update.download_update" +msgstr "下载" + +msgid "update.needs_reload" +msgstr "需要重新加载项目以应用更新。" + +msgid "update.reload_ok_button" +msgstr "重新加载" + +msgid "update.reload_cancel_button" +msgstr "暂不重新加载" + +msgid "update.reload_project" +msgstr "重新加载" + +msgid "update.release_notes" +msgstr "查看发行注记" + +msgid "update.success" +msgstr "v{version} 已成功安装并应用。" + +msgid "update.failed" +msgstr "更新失败。" + +msgid "runtime.no_resource" +msgstr "找不到资源。" + +msgid "runtime.no_content" +msgstr "资源“{file_path}”为空。" + +msgid "runtime.errors" +msgstr "文件中存在{errrors}个错误。" + +msgid "runtime.error_detail" +msgstr "第{index}行:{message}" + +msgid "runtime.errors_see_details" +msgstr "文件中存在{errrors}个错误。请查看调试输出。" + +msgid "runtime.invalid_expression" +msgstr "表达式“{expression}”无效:{error}" + +msgid "runtime.array_index_out_of_bounds" +msgstr "数组索引“{index}”越界。(数组名:“{array}”)" + +msgid "runtime.left_hand_size_cannot_be_assigned_to" +msgstr "表达式左侧的变量无法被赋值。" + +msgid "runtime.key_not_found" +msgstr "键“{key}”在字典“{dictionary}”中不存在。" + +msgid "runtime.property_not_found" +msgstr "“{property}”不存在。(全局变量:{states})" + +msgid "runtime.property_not_found_missing_export" +msgstr "“{property}”不存在。(全局变量:{states})你可能需要添加一个修饰词 [Export]。" + +msgid "runtime.method_not_found" +msgstr "“{method}”不存在。(全局变量:{states})" + +msgid "runtime.signal_not_found" +msgstr "“{sighal_name}”不存在。(全局变量:{states})" + +msgid "runtime.method_not_callable" +msgstr "{method}不是对象“{object}”上的函数。" + +msgid "runtime.unknown_operator" +msgstr "未知操作符。" + +msgid "runtime.something_went_wrong" +msgstr "有什么出错了。" diff --git a/addons/dialogue_manager/l10n/zh_TW.po b/addons/dialogue_manager/l10n/zh_TW.po new file mode 100644 index 0000000..3bcf153 --- /dev/null +++ b/addons/dialogue_manager/l10n/zh_TW.po @@ -0,0 +1,408 @@ +msgid "" +msgstr "" +"Project-Id-Version: Dialogue Manager\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: 憨憨羊の宇航鴿鴿\n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.4\n" + +msgid "start_a_new_file" +msgstr "創建新檔案" + +msgid "open_a_file" +msgstr "開啟已有檔案" + +msgid "open.open" +msgstr "開啟……" + +msgid "open.no_recent_files" +msgstr "無歷史記錄" + +msgid "open.clear_recent_files" +msgstr "清空歷史記錄" + +msgid "save_all_files" +msgstr "儲存所有檔案" + +msgid "test_dialogue" +msgstr "測試對話" + +msgid "search_for_text" +msgstr "搜尋……" + +msgid "insert" +msgstr "插入" + +msgid "translations" +msgstr "翻譯" + +msgid "settings" +msgstr "設定" + +msgid "show_support" +msgstr "支援 Dialogue Manager" + +msgid "docs" +msgstr "文檔" + +msgid "insert.wave_bbcode" +msgstr "BBCode [lb]wave[rb]" + +msgid "insert.shake_bbcode" +msgstr "BBCode [lb]wave[rb]" + +msgid "insert.typing_pause" +msgstr "輸入間隔" + +msgid "insert.typing_speed_change" +msgstr "輸入速度變更" + +msgid "insert.auto_advance" +msgstr "自動切行" + +msgid "insert.templates" +msgstr "模板" + +msgid "insert.title" +msgstr "標題" + +msgid "insert.dialogue" +msgstr "對話" + +msgid "insert.response" +msgstr "回覆選項" + +msgid "insert.random_lines" +msgstr "隨機行" + +msgid "insert.random_text" +msgstr "隨機文本" + +msgid "insert.actions" +msgstr "操作" + +msgid "insert.jump" +msgstr "標題間跳轉" + +msgid "insert.end_dialogue" +msgstr "結束對話" + +msgid "generate_line_ids" +msgstr "生成行 ID" + +msgid "save_to_csv" +msgstr "生成 CSV" + +msgid "import_from_csv" +msgstr "從 CSV 匯入" + +msgid "confirm_close" +msgstr "是否要儲存到“{path}”?" + +msgid "confirm_close.save" +msgstr "儲存" + +msgid "confirm_close.discard" +msgstr "不儲存" + +msgid "buffer.save" +msgstr "儲存" + +msgid "buffer.save_as" +msgstr "儲存爲……" + +msgid "buffer.close" +msgstr "關閉" + +msgid "buffer.close_all" +msgstr "全部關閉" + +msgid "buffer.close_other_files" +msgstr "關閉其他檔案" + +msgid "buffer.copy_file_path" +msgstr "複製檔案位置" + +msgid "buffer.show_in_filesystem" +msgstr "在 Godot 側邊欄中顯示" + +msgid "settings.revert_to_default_test_scene" +msgstr "重置測試場景設定" + +msgid "settings.autoload" +msgstr "Autoload" + +msgid "settings.path" +msgstr "路徑" + +msgid "settings.new_template" +msgstr "新建檔案時自動插入模板" + +msgid "settings.missing_keys" +msgstr "將翻譯鍵缺失視爲錯誤" + +msgid "settings.missing_keys_hint" +msgstr "如果你使用靜態鍵,這將會幫助你尋找未添加至翻譯檔案的鍵。" + +msgid "settings.wrap_long_lines" +msgstr "自動折行" + +msgid "settings.characters_translations" +msgstr "在翻譯檔案中匯出角色名。" + +msgid "settings.include_failed_responses" +msgstr "在判斷條件失敗時仍顯示回復選項" + +msgid "settings.ignore_missing_state_values" +msgstr "忽略全局變量缺失錯誤(不建議)" + +msgid "settings.custom_test_scene" +msgstr "自訂測試場景(必須繼承自BaseDialogueTestScene)" + +msgid "settings.default_csv_locale" +msgstr "預設 CSV 區域格式" + +msgid "settings.states_shortcuts" +msgstr "全局變量映射" + +msgid "settings.states_message" +msgstr "當一個 Autoload 在這裏被勾選,他的所有成員會被映射爲全局變量。" + +msgid "settings.states_hint" +msgstr "比如,當你開啓對於“Foo”的映射時,你可以將“Foo.bar”簡寫成“bar”。" + +msgid "n_of_n" +msgstr "第{index}個,共{total}個" + +msgid "search.previous" +msgstr "搜尋上一個" + +msgid "search.next" +msgstr "搜尋下一個" + +msgid "search.match_case" +msgstr "大小寫敏感" + +msgid "search.toggle_replace" +msgstr "替換" + +msgid "search.replace_with" +msgstr "替換爲" + +msgid "search.replace" +msgstr "替換" + +msgid "search.replace_all" +msgstr "全部替換" + +msgid "files_list.filter" +msgstr "搜尋檔案" + +msgid "titles_list.filter" +msgstr "搜尋標題" + +msgid "errors.key_not_found" +msgstr "鍵“{key}”未找到" + +msgid "errors.line_and_message" +msgstr "第{line}行第{colume}列發生錯誤:{message}" + +msgid "errors_in_script" +msgstr "你的腳本中存在錯誤。請修復錯誤,然後重試。" + +msgid "errors_with_build" +msgstr "請先解決 Dialogue 中的錯誤。" + +msgid "errors.import_errors" +msgstr "被匯入的檔案存在問題。" + +msgid "errors.already_imported" +msgstr "檔案已被匯入。" + +msgid "errors.duplicate_import" +msgstr "匯入名不能重複。" + +msgid "errors.empty_title" +msgstr "標題名不能爲空。" + +msgid "errors.duplicate_title" +msgstr "標題名不能重複。" + +msgid "errors.nested_title" +msgstr "標題不能嵌套。" + +msgid "errors.invalid_title_string" +msgstr "標題名無效。" + +msgid "errors.invalid_title_number" +msgstr "標題不能以數字開始。" + +msgid "errors.unknown_title" +msgstr "標題未定義。" + +msgid "errors.jump_to_invalid_title" +msgstr "標題名無效。" + +msgid "errors.title_has_no_content" +msgstr "目標標題爲空。請替換爲“=> END”。" + +msgid "errors.invalid_expression" +msgstr "表達式無效。" + +msgid "errors.unexpected_condition" +msgstr "未知條件。" + +msgid "errors.duplicate_id" +msgstr "ID 重複。" + +msgid "errors.missing_id" +msgstr "ID 不存在。" + +msgid "errors.invalid_indentation" +msgstr "縮進無效。" + +msgid "errors.condition_has_no_content" +msgstr "條件下方不能爲空。" + +msgid "errors.incomplete_expression" +msgstr "不完整的表達式。" + +msgid "errors.invalid_expression_for_value" +msgstr "無效的賦值表達式。" + +msgid "errors.file_not_found" +msgstr "檔案不存在。" + +msgid "errors.unexpected_end_of_expression" +msgstr "表達式 end 不應存在。" + +msgid "errors.unexpected_function" +msgstr "函數不應存在。" + +msgid "errors.unexpected_bracket" +msgstr "方括號不應存在。" + +msgid "errors.unexpected_closing_bracket" +msgstr "方括號不應存在。" + +msgid "errors.missing_closing_bracket" +msgstr "閉方括號不存在。" + +msgid "errors.unexpected_operator" +msgstr "操作符不應存在。" + +msgid "errors.unexpected_comma" +msgstr "逗號不應存在。" + +msgid "errors.unexpected_colon" +msgstr "冒號不應存在。" + +msgid "errors.unexpected_dot" +msgstr "句號不應存在。" + +msgid "errors.unexpected_boolean" +msgstr "布爾值不應存在。" + +msgid "errors.unexpected_string" +msgstr "字符串不應存在。" + +msgid "errors.unexpected_number" +msgstr "數字不應存在。" + +msgid "errors.unexpected_variable" +msgstr "標識符不應存在。" + +msgid "errors.invalid_index" +msgstr "索引無效。" + +msgid "errors.unexpected_assignment" +msgstr "不應在條件判斷中使用 = ,應使用 == 。" + +msgid "errors.unknown" +msgstr "語法錯誤。" + +msgid "update.available" +msgstr "v{version} 更新可用。" + +msgid "update.is_available_for_download" +msgstr "v%s 已經可以下載。" + +msgid "update.downloading" +msgstr "正在下載更新……" + +msgid "update.download_update" +msgstr "下載" + +msgid "update.needs_reload" +msgstr "需要重新加載項目以套用更新。" + +msgid "update.reload_ok_button" +msgstr "重新加載" + +msgid "update.reload_cancel_button" +msgstr "暫不重新加載" + +msgid "update.reload_project" +msgstr "重新加載" + +msgid "update.release_notes" +msgstr "查看發行註記" + +msgid "update.success" +msgstr "v{version} 已成功安裝並套用。" + +msgid "update.failed" +msgstr "更新失敗。" + +msgid "runtime.no_resource" +msgstr "找不到資源。" + +msgid "runtime.no_content" +msgstr "資源“{file_path}”爲空。" + +msgid "runtime.errors" +msgstr "檔案中存在{errrors}個錯誤。" + +msgid "runtime.error_detail" +msgstr "第{index}行:{message}" + +msgid "runtime.errors_see_details" +msgstr "檔案中存在{errrors}個錯誤。請查看調試輸出。" + +msgid "runtime.invalid_expression" +msgstr "表達式“{expression}”無效:{error}" + +msgid "runtime.array_index_out_of_bounds" +msgstr "數組索引“{index}”越界。(數組名:“{array}”)" + +msgid "runtime.left_hand_size_cannot_be_assigned_to" +msgstr "表達式左側的變量無法被賦值。" + +msgid "runtime.key_not_found" +msgstr "鍵“{key}”在字典“{dictionary}”中不存在。" + +msgid "runtime.property_not_found" +msgstr "“{property}”不存在。(全局變量:{states})" + +msgid "runtime.method_not_found" +msgstr "“{method}”不存在。(全局變量:{states})" + +msgid "runtime.signal_not_found" +msgstr "“{sighal_name}”不存在。(全局變量:{states})" + +msgid "runtime.property_not_found_missing_export" +msgstr "“{property}”不存在。(全局變量:{states})你可能需要添加一個修飾詞 [Export]。" + +msgid "runtime.method_not_callable" +msgstr "{method}不是對象“{object}”上的函數。" + +msgid "runtime.unknown_operator" +msgstr "未知操作符。" + +msgid "runtime.something_went_wrong" +msgstr "有什麼出錯了。" diff --git a/addons/dialogue_manager/plugin.cfg b/addons/dialogue_manager/plugin.cfg new file mode 100644 index 0000000..572ad9f --- /dev/null +++ b/addons/dialogue_manager/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Dialogue Manager" +description="A simple but powerful branching dialogue system" +author="Nathan Hoad" +version="2.38.0" +script="plugin.gd" diff --git a/addons/dialogue_manager/plugin.gd b/addons/dialogue_manager/plugin.gd new file mode 100644 index 0000000..70836f3 --- /dev/null +++ b/addons/dialogue_manager/plugin.gd @@ -0,0 +1,276 @@ +@tool +extends EditorPlugin + + +const DialogueConstants = preload("./constants.gd") +const DialogueImportPlugin = preload("./import_plugin.gd") +const DialogueTranslationParserPlugin = preload("./editor_translation_parser_plugin.gd") +const DialogueSettings = preload("./settings.gd") +const DialogueCache = preload("./components/dialogue_cache.gd") +const MainView = preload("./views/main_view.tscn") + + +var import_plugin: DialogueImportPlugin +var translation_parser_plugin: DialogueTranslationParserPlugin +var main_view +var dialogue_cache: DialogueCache + + +func _enter_tree() -> void: + add_autoload_singleton("DialogueManager", get_plugin_path() + "/dialogue_manager.gd") + + if Engine.is_editor_hint(): + Engine.set_meta("DialogueManagerPlugin", self) + + DialogueSettings.prepare() + + import_plugin = DialogueImportPlugin.new() + add_import_plugin(import_plugin) + + translation_parser_plugin = DialogueTranslationParserPlugin.new() + add_translation_parser_plugin(translation_parser_plugin) + + main_view = MainView.instantiate() + main_view.editor_plugin = self + get_editor_interface().get_editor_main_screen().add_child(main_view) + _make_visible(false) + + dialogue_cache = DialogueCache.new() + main_view.add_child(dialogue_cache) + Engine.set_meta("DialogueCache", dialogue_cache) + + _update_localization() + + get_editor_interface().get_file_system_dock().files_moved.connect(_on_files_moved) + get_editor_interface().get_file_system_dock().file_removed.connect(_on_file_removed) + + add_tool_menu_item("Create copy of dialogue example balloon...", _copy_dialogue_balloon) + + # Prevent the project from showing as unsaved even though it was only just opened + if Engine.get_physics_frames() == 0: + var timer: Timer = Timer.new() + var suppress_unsaved_marker: Callable + suppress_unsaved_marker = func(): + if Engine.get_frames_per_second() >= 10: + timer.stop() + get_editor_interface().save_all_scenes() + timer.queue_free() + timer.timeout.connect(suppress_unsaved_marker) + add_child(timer) + timer.start(0.1) + + +func _exit_tree() -> void: + remove_autoload_singleton("DialogueManager") + + remove_import_plugin(import_plugin) + import_plugin = null + + remove_translation_parser_plugin(translation_parser_plugin) + translation_parser_plugin = null + + if is_instance_valid(main_view): + main_view.queue_free() + + Engine.remove_meta("DialogueManagerPlugin") + Engine.remove_meta("DialogueCache") + + get_editor_interface().get_file_system_dock().files_moved.disconnect(_on_files_moved) + get_editor_interface().get_file_system_dock().file_removed.disconnect(_on_file_removed) + + remove_tool_menu_item("Create copy of dialogue example balloon...") + + +func _has_main_screen() -> bool: + return true + + +func _make_visible(next_visible: bool) -> void: + if is_instance_valid(main_view): + main_view.visible = next_visible + + +func _get_plugin_name() -> String: + return "Dialogue" + + +func _get_plugin_icon() -> Texture2D: + return load(get_plugin_path() + "/assets/icon.svg") + + +func _handles(object) -> bool: + var editor_settings: EditorSettings = get_editor_interface().get_editor_settings() + var external_editor: String = editor_settings.get_setting("text_editor/external/exec_path") + var use_external_editor: bool = editor_settings.get_setting("text_editor/external/use_external_editor") and external_editor != "" + if object is DialogueResource and use_external_editor and DialogueSettings.get_user_value("open_in_external_editor", false): + var project_path: String = ProjectSettings.globalize_path("res://") + var file_path: String = ProjectSettings.globalize_path(object.resource_path) + OS.create_process(external_editor, [project_path, file_path]) + return false + + return object is DialogueResource + + +func _edit(object) -> void: + if is_instance_valid(main_view) and is_instance_valid(object): + main_view.open_resource(object) + + +func _apply_changes() -> void: + if is_instance_valid(main_view): + main_view.apply_changes() + _update_localization() + + +func _build() -> bool: + # If this is the dotnet Godot then we need to check if the solution file exists + if ProjectSettings.has_setting("dotnet/project/solution_directory"): + var directory: String = ProjectSettings.get("dotnet/project/solution_directory") + var file_name: String = ProjectSettings.get("dotnet/project/assembly_name") + var has_dotnet_solution: bool = FileAccess.file_exists("res://%s/%s.sln" % [directory, file_name]) + DialogueSettings.set_user_value("has_dotnet_solution", has_dotnet_solution) + + # Ignore errors in other files if we are just running the test scene + if DialogueSettings.get_user_value("is_running_test_scene", true): return true + + if dialogue_cache != null: + var files_with_errors = dialogue_cache.get_files_with_errors() + if files_with_errors.size() > 0: + for dialogue_file in files_with_errors: + push_error("You have %d error(s) in %s" % [dialogue_file.errors.size(), dialogue_file.path]) + get_editor_interface().edit_resource(load(files_with_errors[0].path)) + main_view.show_build_error_dialog() + return false + + return true + + +## Get the current version +func get_version() -> String: + var config: ConfigFile = ConfigFile.new() + config.load(get_plugin_path() + "/plugin.cfg") + return config.get_value("plugin", "version") + + +## Get the current path of the plugin +func get_plugin_path() -> String: + return get_script().resource_path.get_base_dir() + + +## Update references to a moved file +func update_import_paths(from_path: String, to_path: String) -> void: + dialogue_cache.move_file_path(from_path, to_path) + + # Reopen the file if it's already open + if main_view.current_file_path == from_path: + if to_path == "": + main_view.close_file(from_path) + else: + main_view.current_file_path = "" + main_view.open_file(to_path) + + # Update any other files that import the moved file + var dependents = dialogue_cache.get_files_with_dependency(from_path) + for dependent in dependents: + dependent.dependencies.remove_at(dependent.dependencies.find(from_path)) + dependent.dependencies.append(to_path) + + # Update the live buffer + if main_view.current_file_path == dependent.path: + main_view.code_edit.text = main_view.code_edit.text.replace(from_path, to_path) + main_view.pristine_text = main_view.code_edit.text + + # Open the file and update the path + var file: FileAccess = FileAccess.open(dependent.path, FileAccess.READ) + var text = file.get_as_text().replace(from_path, to_path) + file.close() + + file = FileAccess.open(dependent.path, FileAccess.WRITE) + file.store_string(text) + file.close() + + +func _update_localization() -> void: + var dialogue_files = dialogue_cache.get_files() + + # Add any new files to POT generation + var files_for_pot: PackedStringArray = ProjectSettings.get_setting("internationalization/locale/translations_pot_files", []) + var files_for_pot_changed: bool = false + for path in dialogue_files: + if not files_for_pot.has(path): + files_for_pot.append(path) + files_for_pot_changed = true + + # Remove any POT references that don't exist any more + for i in range(files_for_pot.size() - 1, -1, -1): + var file_for_pot: String = files_for_pot[i] + if file_for_pot.get_extension() == "dialogue" and not dialogue_files.has(file_for_pot): + files_for_pot.remove_at(i) + files_for_pot_changed = true + + # Update project settings if POT changed + if files_for_pot_changed: + ProjectSettings.set_setting("internationalization/locale/translations_pot_files", files_for_pot) + ProjectSettings.save() + + +### Callbacks + + +func _copy_dialogue_balloon() -> void: + var scale: float = get_editor_interface().get_editor_scale() + var directory_dialog: FileDialog = FileDialog.new() + var label: Label = Label.new() + label.text = "Dialogue balloon files will be copied into chosen directory." + directory_dialog.get_vbox().add_child(label) + directory_dialog.file_mode = FileDialog.FILE_MODE_OPEN_DIR + directory_dialog.min_size = Vector2(600, 500) * scale + directory_dialog.dir_selected.connect(func(path): + var plugin_path: String = get_plugin_path() + + var is_dotnet: bool = DialogueSettings.has_dotnet_solution() + var balloon_path: String = path + ("/Balloon.tscn" if is_dotnet else "/balloon.tscn") + var balloon_script_path: String = path + ("/DialogueBalloon.cs" if is_dotnet else "/balloon.gd") + + # Copy the balloon scene file and change the script reference + var is_small_window: bool = ProjectSettings.get_setting("display/window/size/viewport_width") < 400 + var example_balloon_file_name: String = "small_example_balloon.tscn" if is_small_window else "example_balloon.tscn" + var example_balloon_script_file_name: String = "ExampleBalloon.cs" if is_dotnet else "example_balloon.gd" + var file: FileAccess = FileAccess.open(plugin_path + "/example_balloon/" + example_balloon_file_name, FileAccess.READ) + var file_contents: String = file.get_as_text().replace(plugin_path + "/example_balloon/example_balloon.gd", balloon_script_path) + file = FileAccess.open(balloon_path, FileAccess.WRITE) + file.store_string(file_contents) + file.close() + + # Copy the script file + file = FileAccess.open(plugin_path + "/example_balloon/" + example_balloon_script_file_name, FileAccess.READ) + file_contents = file.get_as_text() + if is_dotnet: + file_contents = file_contents.replace("class ExampleBalloon", "class DialogueBalloon") + file = FileAccess.open(balloon_script_path, FileAccess.WRITE) + file.store_string(file_contents) + file.close() + + get_editor_interface().get_resource_filesystem().scan() + get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", balloon_path) + + DialogueSettings.set_setting("balloon_path", balloon_path) + + directory_dialog.queue_free() + ) + get_editor_interface().get_base_control().add_child(directory_dialog) + directory_dialog.popup_centered() + + +### Signals + + +func _on_files_moved(old_file: String, new_file: String) -> void: + update_import_paths(old_file, new_file) + DialogueSettings.move_recent_file(old_file, new_file) + + +func _on_file_removed(file: String) -> void: + update_import_paths(file, "") + if is_instance_valid(main_view): + main_view.close_file(file) diff --git a/addons/dialogue_manager/settings.gd b/addons/dialogue_manager/settings.gd new file mode 100644 index 0000000..b968a84 --- /dev/null +++ b/addons/dialogue_manager/settings.gd @@ -0,0 +1,184 @@ +@tool +extends Node + + +const DialogueConstants = preload("./constants.gd") + + +### Editor config + +const DEFAULT_SETTINGS = { + states = [], + missing_translations_are_errors = false, + export_characters_in_translation = true, + wrap_lines = false, + new_with_template = true, + include_all_responses = false, + ignore_missing_state_values = false, + custom_test_scene_path = preload("./test_scene.tscn").resource_path, + default_csv_locale = "en", + balloon_path = "", + create_lines_for_responses_with_characters = true, + include_character_in_translation_exports = false, + include_notes_in_translation_exports = false +} + + +static func prepare() -> void: + # Migrate previous keys + for key in [ + "states", + "missing_translations_are_errors", + "export_characters_in_translation", + "wrap_lines", + "new_with_template", + "include_all_responses", + "custom_test_scene_path" + ]: + if ProjectSettings.has_setting("dialogue_manager/%s" % key): + var value = ProjectSettings.get_setting("dialogue_manager/%s" % key) + ProjectSettings.set_setting("dialogue_manager/%s" % key, null) + set_setting(key, value) + + # Set up initial settings + for setting in DEFAULT_SETTINGS: + var setting_name: String = "dialogue_manager/general/%s" % setting + if not ProjectSettings.has_setting(setting_name): + set_setting(setting, DEFAULT_SETTINGS[setting]) + ProjectSettings.set_initial_value(setting_name, DEFAULT_SETTINGS[setting]) + if setting.ends_with("_path"): + ProjectSettings.add_property_info({ + "name": setting_name, + "type": TYPE_STRING, + "hint": PROPERTY_HINT_FILE, + }) + + ProjectSettings.save() + + +static func set_setting(key: String, value) -> void: + ProjectSettings.set_setting("dialogue_manager/general/%s" % key, value) + ProjectSettings.set_initial_value("dialogue_manager/general/%s" % key, DEFAULT_SETTINGS[key]) + ProjectSettings.save() + + +static func get_setting(key: String, default): + if ProjectSettings.has_setting("dialogue_manager/general/%s" % key): + return ProjectSettings.get_setting("dialogue_manager/general/%s" % key) + else: + return default + + +static func get_settings(only_keys: PackedStringArray = []) -> Dictionary: + var settings: Dictionary = {} + for key in DEFAULT_SETTINGS.keys(): + if only_keys.is_empty() or key in only_keys: + settings[key] = get_setting(key, DEFAULT_SETTINGS[key]) + return settings + + +### User config + + +static func get_user_config() -> Dictionary: + var user_config: Dictionary = { + check_for_updates = true, + just_refreshed = null, + recent_files = [], + reopen_files = [], + most_recent_reopen_file = "", + carets = {}, + run_title = "", + run_resource_path = "", + is_running_test_scene = false, + has_dotnet_solution = false, + open_in_external_editor = false + } + + if FileAccess.file_exists(DialogueConstants.USER_CONFIG_PATH): + var file: FileAccess = FileAccess.open(DialogueConstants.USER_CONFIG_PATH, FileAccess.READ) + user_config.merge(JSON.parse_string(file.get_as_text()), true) + + return user_config + + +static func save_user_config(user_config: Dictionary) -> void: + var file: FileAccess = FileAccess.open(DialogueConstants.USER_CONFIG_PATH, FileAccess.WRITE) + file.store_string(JSON.stringify(user_config)) + + +static func set_user_value(key: String, value) -> void: + var user_config: Dictionary = get_user_config() + user_config[key] = value + save_user_config(user_config) + + +static func get_user_value(key: String, default = null): + return get_user_config().get(key, default) + + +static func add_recent_file(path: String) -> void: + var recent_files: Array = get_user_value("recent_files", []) + if path in recent_files: + recent_files.erase(path) + recent_files.insert(0, path) + set_user_value("recent_files", recent_files) + + +static func move_recent_file(from_path: String, to_path: String) -> void: + var recent_files: Array = get_user_value("recent_files", []) + for i in range(0, recent_files.size()): + if recent_files[i] == from_path: + recent_files[i] = to_path + set_user_value("recent_files", recent_files) + + +static func remove_recent_file(path: String) -> void: + var recent_files: Array = get_user_value("recent_files", []) + if path in recent_files: + recent_files.erase(path) + set_user_value("recent_files", recent_files) + + +static func get_recent_files() -> Array: + return get_user_value("recent_files", []) + + +static func clear_recent_files() -> void: + set_user_value("recent_files", []) + set_user_value("carets", {}) + + +static func set_caret(path: String, cursor: Vector2) -> void: + var carets: Dictionary = get_user_value("carets", {}) + carets[path] = { + x = cursor.x, + y = cursor.y + } + set_user_value("carets", carets) + + +static func get_caret(path: String) -> Vector2: + var carets = get_user_value("carets", {}) + if carets.has(path): + var caret = carets.get(path) + return Vector2(caret.x, caret.y) + else: + return Vector2.ZERO + + +static func has_dotnet_solution() -> bool: + if get_user_value("has_dotnet_solution", false): return true + + if ProjectSettings.has_setting("dotnet/project/solution_directory"): + var directory: String = ProjectSettings.get("dotnet/project/solution_directory") + var file_name: String = ProjectSettings.get("dotnet/project/assembly_name") + var has_dotnet_solution: bool = FileAccess.file_exists("res://%s/%s.sln" % [directory, file_name]) + set_user_value("has_dotnet_solution", has_dotnet_solution) + return has_dotnet_solution + else: + var plugin_path: String = new().get_script().resource_path.get_base_dir() + if not ResourceLoader.exists(plugin_path + "/DialogueManager.cs"): return false + if load(plugin_path + "/DialogueManager.cs") == null: return false + + return true diff --git a/addons/dialogue_manager/test_scene.gd b/addons/dialogue_manager/test_scene.gd new file mode 100644 index 0000000..5fc073e --- /dev/null +++ b/addons/dialogue_manager/test_scene.gd @@ -0,0 +1,31 @@ +class_name BaseDialogueTestScene extends Node2D + + +const DialogueSettings = preload("./settings.gd") + + +@onready var title: String = DialogueSettings.get_user_value("run_title") +@onready var resource: DialogueResource = load(DialogueSettings.get_user_value("run_resource_path")) + + +func _ready(): + var screen_index: int = DisplayServer.get_primary_screen() + DisplayServer.window_set_position(Vector2(DisplayServer.screen_get_position(screen_index)) + (DisplayServer.screen_get_size(screen_index) - DisplayServer.window_get_size()) * 0.5) + DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) + + # Normally you can just call DialogueManager directly but doing so before the plugin has been + # enabled in settings will throw a compiler error here so I'm using get_singleton instead. + var dialogue_manager = Engine.get_singleton("DialogueManager") + dialogue_manager.dialogue_ended.connect(_on_dialogue_ended) + dialogue_manager.show_dialogue_balloon(resource, title) + + +func _enter_tree() -> void: + DialogueSettings.set_user_value("is_running_test_scene", false) + + +### Signals + + +func _on_dialogue_ended(_resource: DialogueResource): + get_tree().quit() diff --git a/addons/dialogue_manager/test_scene.tscn b/addons/dialogue_manager/test_scene.tscn new file mode 100644 index 0000000..f2bbd8d --- /dev/null +++ b/addons/dialogue_manager/test_scene.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://addons/dialogue_manager/test_scene.gd" id="1_yupoh"] + + +[node name="TestScene" type="Node2D"] +script = ExtResource("1_yupoh") diff --git a/addons/dialogue_manager/utilities/builtins.gd b/addons/dialogue_manager/utilities/builtins.gd new file mode 100644 index 0000000..f8442d4 --- /dev/null +++ b/addons/dialogue_manager/utilities/builtins.gd @@ -0,0 +1,468 @@ +extends Object + + +const DialogueConstants = preload("../constants.gd") + +const SUPPORTED_BUILTIN_TYPES = [ + TYPE_ARRAY, + TYPE_VECTOR2, + TYPE_VECTOR3, + TYPE_VECTOR4, + TYPE_DICTIONARY, + TYPE_QUATERNION, + TYPE_COLOR, + TYPE_SIGNAL +] + + +static var resolve_method_error: Error = OK + + +static func is_supported(thing) -> bool: + return typeof(thing) in SUPPORTED_BUILTIN_TYPES + + +static func resolve_property(builtin, property: String): + match typeof(builtin): + TYPE_ARRAY, TYPE_DICTIONARY, TYPE_QUATERNION: + return builtin[property] + + # Some types have constants that we need to manually resolve + + TYPE_VECTOR2: + return resolve_vector2_property(builtin, property) + TYPE_VECTOR3: + return resolve_vector3_property(builtin, property) + TYPE_VECTOR4: + return resolve_vector4_property(builtin, property) + TYPE_COLOR: + return resolve_color_property(builtin, property) + + +static func resolve_method(thing, method_name: String, args: Array): + resolve_method_error = OK + + # Resolve static methods manually + match typeof(thing): + TYPE_VECTOR2: + match method_name: + "from_angle": + return Vector2.from_angle(args[0]) + + TYPE_COLOR: + match method_name: + "from_hsv": + return Color.from_hsv(args[0], args[1], args[2]) if args.size() == 3 else Color.from_hsv(args[0], args[1], args[2], args[3]) + "from_ok_hsl": + return Color.from_ok_hsl(args[0], args[1], args[2]) if args.size() == 3 else Color.from_ok_hsl(args[0], args[1], args[2], args[3]) + "from_rgbe9995": + return Color.from_rgbe9995(args[0]) + "from_string": + return Color.from_string(args[0], args[1]) + + TYPE_QUATERNION: + match method_name: + "from_euler": + return Quaternion.from_euler(args[0]) + + # Anything else can be evaulatated automatically + var references: Array = ["thing"] + for i in range(0, args.size()): + references.append("arg%d" % i) + var expression = Expression.new() + if expression.parse("thing.%s(%s)" % [method_name, ",".join(references.slice(1))], references) != OK: + assert(false, expression.get_error_text()) + var result = expression.execute([thing] + args, null, false) + if expression.has_execute_failed(): + resolve_method_error = ERR_CANT_RESOLVE + return null + + return result + + +static func has_resolve_method_failed() -> bool: + return resolve_method_error != OK + + +static func resolve_color_property(color: Color, property: String): + match property: + "ALICE_BLUE": + return Color.ALICE_BLUE + "ANTIQUE_WHITE": + return Color.ANTIQUE_WHITE + "AQUA": + return Color.AQUA + "AQUAMARINE": + return Color.AQUAMARINE + "AZURE": + return Color.AZURE + "BEIGE": + return Color.BEIGE + "BISQUE": + return Color.BISQUE + "BLACK": + return Color.BLACK + "BLANCHED_ALMOND": + return Color.BLANCHED_ALMOND + "BLUE": + return Color.BLUE + "BLUE_VIOLET": + return Color.BLUE_VIOLET + "BROWN": + return Color.BROWN + "BURLYWOOD": + return Color.BURLYWOOD + "CADET_BLUE": + return Color.CADET_BLUE + "CHARTREUSE": + return Color.CHARTREUSE + "CHOCOLATE": + return Color.CHOCOLATE + "CORAL": + return Color.CORAL + "CORNFLOWER_BLUE": + return Color.CORNFLOWER_BLUE + "CORNSILK": + return Color.CORNSILK + "CRIMSON": + return Color.CRIMSON + "CYAN": + return Color.CYAN + "DARK_BLUE": + return Color.DARK_BLUE + "DARK_CYAN": + return Color.DARK_CYAN + "DARK_GOLDENROD": + return Color.DARK_GOLDENROD + "DARK_GRAY": + return Color.DARK_GRAY + "DARK_GREEN": + return Color.DARK_GREEN + "DARK_KHAKI": + return Color.DARK_KHAKI + "DARK_MAGENTA": + return Color.DARK_MAGENTA + "DARK_OLIVE_GREEN": + return Color.DARK_OLIVE_GREEN + "DARK_ORANGE": + return Color.DARK_ORANGE + "DARK_ORCHID": + return Color.DARK_ORCHID + "DARK_RED": + return Color.DARK_RED + "DARK_SALMON": + return Color.DARK_SALMON + "DARK_SEA_GREEN": + return Color.DARK_SEA_GREEN + "DARK_SLATE_BLUE": + return Color.DARK_SLATE_BLUE + "DARK_SLATE_GRAY": + return Color.DARK_SLATE_GRAY + "DARK_TURQUOISE": + return Color.DARK_TURQUOISE + "DARK_VIOLET": + return Color.DARK_VIOLET + "DEEP_PINK": + return Color.DEEP_PINK + "DEEP_SKY_BLUE": + return Color.DEEP_SKY_BLUE + "DIM_GRAY": + return Color.DIM_GRAY + "DODGER_BLUE": + return Color.DODGER_BLUE + "FIREBRICK": + return Color.FIREBRICK + "FLORAL_WHITE": + return Color.FLORAL_WHITE + "FOREST_GREEN": + return Color.FOREST_GREEN + "FUCHSIA": + return Color.FUCHSIA + "GAINSBORO": + return Color.GAINSBORO + "GHOST_WHITE": + return Color.GHOST_WHITE + "GOLD": + return Color.GOLD + "GOLDENROD": + return Color.GOLDENROD + "GRAY": + return Color.GRAY + "GREEN": + return Color.GREEN + "GREEN_YELLOW": + return Color.GREEN_YELLOW + "HONEYDEW": + return Color.HONEYDEW + "HOT_PINK": + return Color.HOT_PINK + "INDIAN_RED": + return Color.INDIAN_RED + "INDIGO": + return Color.INDIGO + "IVORY": + return Color.IVORY + "KHAKI": + return Color.KHAKI + "LAVENDER": + return Color.LAVENDER + "LAVENDER_BLUSH": + return Color.LAVENDER_BLUSH + "LAWN_GREEN": + return Color.LAWN_GREEN + "LEMON_CHIFFON": + return Color.LEMON_CHIFFON + "LIGHT_BLUE": + return Color.LIGHT_BLUE + "LIGHT_CORAL": + return Color.LIGHT_CORAL + "LIGHT_CYAN": + return Color.LIGHT_CYAN + "LIGHT_GOLDENROD": + return Color.LIGHT_GOLDENROD + "LIGHT_GRAY": + return Color.LIGHT_GRAY + "LIGHT_GREEN": + return Color.LIGHT_GREEN + "LIGHT_PINK": + return Color.LIGHT_PINK + "LIGHT_SALMON": + return Color.LIGHT_SALMON + "LIGHT_SEA_GREEN": + return Color.LIGHT_SEA_GREEN + "LIGHT_SKY_BLUE": + return Color.LIGHT_SKY_BLUE + "LIGHT_SLATE_GRAY": + return Color.LIGHT_SLATE_GRAY + "LIGHT_STEEL_BLUE": + return Color.LIGHT_STEEL_BLUE + "LIGHT_YELLOW": + return Color.LIGHT_YELLOW + "LIME": + return Color.LIME + "LIME_GREEN": + return Color.LIME_GREEN + "LINEN": + return Color.LINEN + "MAGENTA": + return Color.MAGENTA + "MAROON": + return Color.MAROON + "MEDIUM_AQUAMARINE": + return Color.MEDIUM_AQUAMARINE + "MEDIUM_BLUE": + return Color.MEDIUM_BLUE + "MEDIUM_ORCHID": + return Color.MEDIUM_ORCHID + "MEDIUM_PURPLE": + return Color.MEDIUM_PURPLE + "MEDIUM_SEA_GREEN": + return Color.MEDIUM_SEA_GREEN + "MEDIUM_SLATE_BLUE": + return Color.MEDIUM_SLATE_BLUE + "MEDIUM_SPRING_GREEN": + return Color.MEDIUM_SPRING_GREEN + "MEDIUM_TURQUOISE": + return Color.MEDIUM_TURQUOISE + "MEDIUM_VIOLET_RED": + return Color.MEDIUM_VIOLET_RED + "MIDNIGHT_BLUE": + return Color.MIDNIGHT_BLUE + "MINT_CREAM": + return Color.MINT_CREAM + "MISTY_ROSE": + return Color.MISTY_ROSE + "MOCCASIN": + return Color.MOCCASIN + "NAVAJO_WHITE": + return Color.NAVAJO_WHITE + "NAVY_BLUE": + return Color.NAVY_BLUE + "OLD_LACE": + return Color.OLD_LACE + "OLIVE": + return Color.OLIVE + "OLIVE_DRAB": + return Color.OLIVE_DRAB + "ORANGE": + return Color.ORANGE + "ORANGE_RED": + return Color.ORANGE_RED + "ORCHID": + return Color.ORCHID + "PALE_GOLDENROD": + return Color.PALE_GOLDENROD + "PALE_GREEN": + return Color.PALE_GREEN + "PALE_TURQUOISE": + return Color.PALE_TURQUOISE + "PALE_VIOLET_RED": + return Color.PALE_VIOLET_RED + "PAPAYA_WHIP": + return Color.PAPAYA_WHIP + "PEACH_PUFF": + return Color.PEACH_PUFF + "PERU": + return Color.PERU + "PINK": + return Color.PINK + "PLUM": + return Color.PLUM + "POWDER_BLUE": + return Color.POWDER_BLUE + "PURPLE": + return Color.PURPLE + "REBECCA_PURPLE": + return Color.REBECCA_PURPLE + "RED": + return Color.RED + "ROSY_BROWN": + return Color.ROSY_BROWN + "ROYAL_BLUE": + return Color.ROYAL_BLUE + "SADDLE_BROWN": + return Color.SADDLE_BROWN + "SALMON": + return Color.SALMON + "SANDY_BROWN": + return Color.SANDY_BROWN + "SEA_GREEN": + return Color.SEA_GREEN + "SEASHELL": + return Color.SEASHELL + "SIENNA": + return Color.SIENNA + "SILVER": + return Color.SILVER + "SKY_BLUE": + return Color.SKY_BLUE + "SLATE_BLUE": + return Color.SLATE_BLUE + "SLATE_GRAY": + return Color.SLATE_GRAY + "SNOW": + return Color.SNOW + "SPRING_GREEN": + return Color.SPRING_GREEN + "STEEL_BLUE": + return Color.STEEL_BLUE + "TAN": + return Color.TAN + "TEAL": + return Color.TEAL + "THISTLE": + return Color.THISTLE + "TOMATO": + return Color.TOMATO + "TRANSPARENT": + return Color.TRANSPARENT + "TURQUOISE": + return Color.TURQUOISE + "VIOLET": + return Color.VIOLET + "WEB_GRAY": + return Color.WEB_GRAY + "WEB_GREEN": + return Color.WEB_GREEN + "WEB_MAROON": + return Color.WEB_MAROON + "WEB_PURPLE": + return Color.WEB_PURPLE + "WHEAT": + return Color.WHEAT + "WHITE": + return Color.WHITE + "WHITE_SMOKE": + return Color.WHITE_SMOKE + "YELLOW": + return Color.YELLOW + "YELLOW_GREEN": + return Color.YELLOW_GREEN + + return color[property] + + +static func resolve_vector2_property(vector: Vector2, property: String): + match property: + "AXIS_X": + return Vector2.AXIS_X + "AXIS_Y": + return Vector2.AXIS_Y + "ZERO": + return Vector2.ZERO + "ONE": + return Vector2.ONE + "INF": + return Vector2.INF + "LEFT": + return Vector2.LEFT + "RIGHT": + return Vector2.RIGHT + "UP": + return Vector2.UP + "DOWN": + return Vector2.DOWN + + return vector[property] + + +static func resolve_vector3_property(vector: Vector3, property: String): + match property: + "AXIS_X": + return Vector3.AXIS_X + "AXIS_Y": + return Vector3.AXIS_Y + "AXIS_Z": + return Vector3.AXIS_Z + "ZERO": + return Vector3.ZERO + "ONE": + return Vector3.ONE + "INF": + return Vector3.INF + "LEFT": + return Vector3.LEFT + "RIGHT": + return Vector3.RIGHT + "UP": + return Vector3.UP + "DOWN": + return Vector3.DOWN + "FORWARD": + return Vector3.FORWARD + "BACK": + return Vector3.BACK + "MODEL_LEFT": + return Vector3(1, 0, 0) + "MODEL_RIGHT": + return Vector3(-1, 0, 0) + "MODEL_TOP": + return Vector3(0, 1, 0) + "MODEL_BOTTOM": + return Vector3(0, -1, 0) + "MODEL_FRONT": + return Vector3(0, 0, 1) + "MODEL_REAR": + return Vector3(0, 0, -1) + + return vector[property] + + +static func resolve_vector4_property(vector: Vector4, property: String): + match property: + "AXIS_X": + return Vector4.AXIS_X + "AXIS_Y": + return Vector4.AXIS_Y + "AXIS_Z": + return Vector4.AXIS_Z + "AXIS_W": + return Vector4.AXIS_W + "ZERO": + return Vector4.ZERO + "ONE": + return Vector4.ONE + "INF": + return Vector4.INF + + return vector[property] diff --git a/addons/dialogue_manager/views/main_view.gd b/addons/dialogue_manager/views/main_view.gd new file mode 100644 index 0000000..445d53d --- /dev/null +++ b/addons/dialogue_manager/views/main_view.gd @@ -0,0 +1,1100 @@ +@tool +extends Control + + +const DialogueConstants = preload("../constants.gd") +const DialogueSettings = preload("../settings.gd") + +const OPEN_OPEN = 100 +const OPEN_CLEAR = 101 + +const TRANSLATIONS_GENERATE_LINE_IDS = 100 +const TRANSLATIONS_SAVE_CHARACTERS_TO_CSV = 201 +const TRANSLATIONS_SAVE_TO_CSV = 202 +const TRANSLATIONS_IMPORT_FROM_CSV = 203 + +const ITEM_SAVE = 100 +const ITEM_SAVE_AS = 101 +const ITEM_CLOSE = 102 +const ITEM_CLOSE_ALL = 103 +const ITEM_CLOSE_OTHERS = 104 +const ITEM_COPY_PATH = 200 +const ITEM_SHOW_IN_FILESYSTEM = 201 + +enum TranslationSource { + CharacterNames, + Lines +} + + +@onready var parse_timer := $ParseTimer + +# Dialogs +@onready var new_dialog: FileDialog = $NewDialog +@onready var save_dialog: FileDialog = $SaveDialog +@onready var open_dialog: FileDialog = $OpenDialog +@onready var export_dialog: FileDialog = $ExportDialog +@onready var import_dialog: FileDialog = $ImportDialog +@onready var errors_dialog: AcceptDialog = $ErrorsDialog +@onready var settings_dialog: AcceptDialog = $SettingsDialog +@onready var settings_view := $SettingsDialog/SettingsView +@onready var build_error_dialog: AcceptDialog = $BuildErrorDialog +@onready var close_confirmation_dialog: ConfirmationDialog = $CloseConfirmationDialog +@onready var updated_dialog: AcceptDialog = $UpdatedDialog +@onready var find_in_files_dialog: AcceptDialog = $FindInFilesDialog +@onready var find_in_files: Control = $FindInFilesDialog/FindInFiles + +# Toolbar +@onready var new_button: Button = %NewButton +@onready var open_button: MenuButton = %OpenButton +@onready var save_all_button: Button = %SaveAllButton +@onready var find_in_files_button: Button = %FindInFilesButton +@onready var test_button: Button = %TestButton +@onready var search_button: Button = %SearchButton +@onready var insert_button: MenuButton = %InsertButton +@onready var translations_button: MenuButton = %TranslationsButton +@onready var settings_button: Button = %SettingsButton +@onready var support_button: Button = %SupportButton +@onready var docs_button: Button = %DocsButton +@onready var version_label: Label = %VersionLabel +@onready var update_button: Button = %UpdateButton + +@onready var search_and_replace := %SearchAndReplace + +# Code editor +@onready var content: HSplitContainer = %Content +@onready var files_list := %FilesList +@onready var files_popup_menu: PopupMenu = %FilesPopupMenu +@onready var title_list := %TitleList +@onready var code_edit := %CodeEdit +@onready var errors_panel := %ErrorsPanel + +# The Dialogue Manager plugin +var editor_plugin: EditorPlugin + +# The currently open file +var current_file_path: String = "": + set(next_current_file_path): + current_file_path = next_current_file_path + files_list.current_file_path = current_file_path + if current_file_path == "": + save_all_button.disabled = true + test_button.disabled = true + search_button.disabled = true + insert_button.disabled = true + translations_button.disabled = true + content.dragger_visibility = SplitContainer.DRAGGER_HIDDEN + files_list.hide() + title_list.hide() + code_edit.hide() + errors_panel.hide() + else: + test_button.disabled = false + search_button.disabled = false + insert_button.disabled = false + translations_button.disabled = false + content.dragger_visibility = SplitContainer.DRAGGER_VISIBLE + files_list.show() + title_list.show() + code_edit.show() + + code_edit.text = open_buffers[current_file_path].text + code_edit.errors = [] + code_edit.clear_undo_history() + code_edit.set_cursor(DialogueSettings.get_caret(current_file_path)) + code_edit.grab_focus() + + _on_code_edit_text_changed() + + errors_panel.errors = [] + code_edit.errors = [] + get: + return current_file_path + +# A reference to the currently open files and their last saved text +var open_buffers: Dictionary = {} + +# Which thing are we exporting translations for? +var translation_source: TranslationSource = TranslationSource.Lines + + +func _ready() -> void: + apply_theme() + + # Start with nothing open + self.current_file_path = "" + + # Set up the update checker + version_label.text = "v%s" % editor_plugin.get_version() + update_button.editor_plugin = editor_plugin + update_button.on_before_refresh = func on_before_refresh(): + # Save everything + DialogueSettings.set_user_value("just_refreshed", { + current_file_path = current_file_path, + open_buffers = open_buffers + }) + return true + + # Did we just load from an addon version refresh? + var just_refreshed = DialogueSettings.get_user_value("just_refreshed", null) + if just_refreshed != null: + DialogueSettings.set_user_value("just_refreshed", null) + call_deferred("load_from_version_refresh", just_refreshed) + + # Hook up the search toolbar + search_and_replace.code_edit = code_edit + + # Connect menu buttons + insert_button.get_popup().id_pressed.connect(_on_insert_button_menu_id_pressed) + translations_button.get_popup().id_pressed.connect(_on_translations_button_menu_id_pressed) + + code_edit.main_view = self + code_edit.wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY if DialogueSettings.get_setting("wrap_lines", false) else TextEdit.LINE_WRAPPING_NONE + var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() + editor_settings.settings_changed.connect(_on_editor_settings_changed) + _on_editor_settings_changed() + + # Reopen any files that were open when Godot was closed + if editor_settings.get_setting("text_editor/behavior/files/restore_scripts_on_load"): + var reopen_files: Array = DialogueSettings.get_user_value("reopen_files", []) + for reopen_file in reopen_files: + open_file(reopen_file) + + self.current_file_path = DialogueSettings.get_user_value("most_recent_reopen_file", "") + + save_all_button.disabled = true + + close_confirmation_dialog.ok_button_text = DialogueConstants.translate(&"confirm_close.save") + close_confirmation_dialog.add_button(DialogueConstants.translate(&"confirm_close.discard"), true, "discard") + + settings_view.editor_plugin = editor_plugin + + errors_dialog.dialog_text = DialogueConstants.translate(&"errors_in_script") + + +func _exit_tree() -> void: + DialogueSettings.set_user_value("reopen_files", open_buffers.keys()) + DialogueSettings.set_user_value("most_recent_reopen_file", self.current_file_path) + + +func _unhandled_input(event: InputEvent) -> void: + if not visible: return + + if event is InputEventKey and event.is_pressed(): + match event.as_text(): + "Ctrl+Alt+S", "Command+Alt+S": + get_viewport().set_input_as_handled() + save_file(current_file_path) + "Ctrl+W", "Command+W": + get_viewport().set_input_as_handled() + close_file(current_file_path) + "Ctrl+F5", "Command+F5": + get_viewport().set_input_as_handled() + _on_test_button_pressed() + "Ctrl+Shift+F", "Command+Shift+F": + get_viewport().set_input_as_handled() + _on_find_in_files_button_pressed() + + +func apply_changes() -> void: + save_files() + + +# Load back to the previous buffer regardless of if it was actually saved +func load_from_version_refresh(just_refreshed: Dictionary) -> void: + if just_refreshed.has("current_file_content"): + # We just loaded from a version before multiple buffers + var file: FileAccess = FileAccess.open(just_refreshed.current_file_path, FileAccess.READ) + var file_text: String = file.get_as_text() + open_buffers[just_refreshed.current_file_path] = { + pristine_text = file_text, + text = just_refreshed.current_file_content + } + else: + open_buffers = just_refreshed.open_buffers + + if just_refreshed.current_file_path != "": + editor_plugin.get_editor_interface().edit_resource(load(just_refreshed.current_file_path)) + else: + editor_plugin.get_editor_interface().set_main_screen_editor("Dialogue") + + updated_dialog.dialog_text = DialogueConstants.translate(&"update.success").format({ version = update_button.get_version() }) + updated_dialog.popup_centered() + + +func new_file(path: String, content: String = "") -> void: + if open_buffers.has(path): + remove_file_from_open_buffers(path) + + var file: FileAccess = FileAccess.open(path, FileAccess.WRITE) + if content == "": + if DialogueSettings.get_setting("new_with_template", true): + file.store_string("\n".join([ + "~ this_is_a_node_title", + "", + "Nathan: [[Hi|Hello|Howdy]], this is some dialogue.", + "Nathan: Here are some choices.", + "- First one", + "\tNathan: You picked the first one.", + "- Second one", + "\tNathan: You picked the second one.", + "- Start again => this_is_a_node_title", + "- End the conversation => END", + "Nathan: For more information see the online documentation.", + "", + "=> END" + ])) + else: + file.store_string(content) + + editor_plugin.get_editor_interface().get_resource_filesystem().scan() + + +# Open a dialogue resource for editing +func open_resource(resource: DialogueResource) -> void: + open_file(resource.resource_path) + + +func open_file(path: String) -> void: + if not open_buffers.has(path): + var file: FileAccess = FileAccess.open(path, FileAccess.READ) + var text = file.get_as_text() + + open_buffers[path] = { + cursor = Vector2.ZERO, + text = text, + pristine_text = text + } + + DialogueSettings.add_recent_file(path) + build_open_menu() + + files_list.files = open_buffers.keys() + files_list.select_file(path) + + self.current_file_path = path + + +func show_file_in_filesystem(path: String) -> void: + var file_system_dock: FileSystemDock = Engine.get_meta("DialogueManagerPlugin") \ + .get_editor_interface() \ + .get_file_system_dock() + + file_system_dock.navigate_to_path(path) + + +# Save any open files +func save_files() -> void: + save_all_button.disabled = true + + var saved_files: PackedStringArray = [] + for path in open_buffers: + if open_buffers[path].text != open_buffers[path].pristine_text: + saved_files.append(path) + save_file(path, false) + + if saved_files.size() > 0: + Engine.get_meta("DialogueCache").reimport_files(saved_files) + + +# Save a file +func save_file(path: String, rescan_file_system: bool = true) -> void: + var buffer = open_buffers[path] + + files_list.mark_file_as_unsaved(path, false) + save_all_button.disabled = files_list.unsaved_files.size() == 0 + + # Don't bother saving if there is nothing to save + if buffer.text == buffer.pristine_text: + return + + buffer.pristine_text = buffer.text + + # Save the current text + var file: FileAccess = FileAccess.open(path, FileAccess.WRITE) + file.store_string(buffer.text) + file.close() + + if rescan_file_system: + Engine.get_meta("DialogueManagerPlugin") \ + .get_editor_interface() \ + .get_resource_filesystem()\ + .scan() + + +func close_file(file: String) -> void: + if not file in open_buffers.keys(): return + + var buffer = open_buffers[file] + + if buffer.text == buffer.pristine_text: + remove_file_from_open_buffers(file) + else: + close_confirmation_dialog.dialog_text = DialogueConstants.translate(&"confirm_close").format({ path = file.get_file() }) + close_confirmation_dialog.popup_centered() + + +func remove_file_from_open_buffers(file: String) -> void: + if not file in open_buffers.keys(): return + + var current_index = open_buffers.keys().find(file) + + open_buffers.erase(file) + if open_buffers.size() == 0: + self.current_file_path = "" + else: + current_index = clamp(current_index, 0, open_buffers.size() - 1) + self.current_file_path = open_buffers.keys()[current_index] + files_list.files = open_buffers.keys() + + +# Apply theme colors and icons to the UI +func apply_theme() -> void: + if is_instance_valid(editor_plugin) and is_instance_valid(code_edit): + var scale: float = editor_plugin.get_editor_interface().get_editor_scale() + var editor_settings = editor_plugin.get_editor_interface().get_editor_settings() + code_edit.theme_overrides = { + scale = scale, + + background_color = editor_settings.get_setting("text_editor/theme/highlighting/background_color"), + current_line_color = editor_settings.get_setting("text_editor/theme/highlighting/current_line_color"), + error_line_color = editor_settings.get_setting("text_editor/theme/highlighting/mark_color"), + + critical_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_markers/critical_color"), + notice_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_markers/notice_color"), + + titles_color = editor_settings.get_setting("text_editor/theme/highlighting/control_flow_keyword_color"), + text_color = editor_settings.get_setting("text_editor/theme/highlighting/text_color"), + conditions_color = editor_settings.get_setting("text_editor/theme/highlighting/keyword_color"), + mutations_color = editor_settings.get_setting("text_editor/theme/highlighting/function_color"), + members_color = editor_settings.get_setting("text_editor/theme/highlighting/member_variable_color"), + strings_color = editor_settings.get_setting("text_editor/theme/highlighting/string_color"), + numbers_color = editor_settings.get_setting("text_editor/theme/highlighting/number_color"), + symbols_color = editor_settings.get_setting("text_editor/theme/highlighting/symbol_color"), + comments_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_color"), + jumps_color = Color(editor_settings.get_setting("text_editor/theme/highlighting/control_flow_keyword_color"), 0.7), + + font_size = editor_settings.get_setting("interface/editor/code_font_size") + } + + new_button.icon = get_theme_icon("New", "EditorIcons") + new_button.tooltip_text = DialogueConstants.translate(&"start_a_new_file") + + open_button.icon = get_theme_icon("Load", "EditorIcons") + open_button.tooltip_text = DialogueConstants.translate(&"open_a_file") + + save_all_button.icon = get_theme_icon("Save", "EditorIcons") + save_all_button.tooltip_text = DialogueConstants.translate(&"start_all_files") + + find_in_files_button.icon = get_theme_icon("ViewportZoom", "EditorIcons") + find_in_files_button.tooltip_text = DialogueConstants.translate(&"find_in_files") + + test_button.icon = get_theme_icon("PlayScene", "EditorIcons") + test_button.tooltip_text = DialogueConstants.translate(&"test_dialogue") + + search_button.icon = get_theme_icon("Search", "EditorIcons") + search_button.tooltip_text = DialogueConstants.translate(&"search_for_text") + + insert_button.icon = get_theme_icon("RichTextEffect", "EditorIcons") + insert_button.text = DialogueConstants.translate(&"insert") + + translations_button.icon = get_theme_icon("Translation", "EditorIcons") + translations_button.text = DialogueConstants.translate(&"translations") + + settings_button.icon = get_theme_icon("Tools", "EditorIcons") + settings_button.tooltip_text = DialogueConstants.translate(&"settings") + + support_button.icon = get_theme_icon("Heart", "EditorIcons") + support_button.text = DialogueConstants.translate(&"sponsor") + support_button.tooltip_text = DialogueConstants.translate(&"show_support") + + docs_button.icon = get_theme_icon("Help", "EditorIcons") + docs_button.text = DialogueConstants.translate(&"docs") + + update_button.apply_theme() + + # Set up the effect menu + var popup: PopupMenu = insert_button.get_popup() + popup.clear() + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.wave_bbcode"), 0) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.shake_bbcode"), 1) + popup.add_separator() + popup.add_icon_item(get_theme_icon("Time", "EditorIcons"), DialogueConstants.translate(&"insert.typing_pause"), 3) + popup.add_icon_item(get_theme_icon("ViewportSpeed", "EditorIcons"), DialogueConstants.translate(&"insert.typing_speed_change"), 4) + popup.add_icon_item(get_theme_icon("DebugNext", "EditorIcons"), DialogueConstants.translate(&"insert.auto_advance"), 5) + popup.add_separator(DialogueConstants.translate(&"insert.templates")) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.title"), 6) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.dialogue"), 7) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.response"), 8) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.random_lines"), 9) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.random_text"), 10) + popup.add_separator(DialogueConstants.translate(&"insert.actions")) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.jump"), 11) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.end_dialogue"), 12) + + # Set up the translations menu + popup = translations_button.get_popup() + popup.clear() + popup.add_icon_item(get_theme_icon("Translation", "EditorIcons"), DialogueConstants.translate(&"generate_line_ids"), TRANSLATIONS_GENERATE_LINE_IDS) + popup.add_separator() + popup.add_icon_item(get_theme_icon("FileList", "EditorIcons"), DialogueConstants.translate(&"save_characters_to_csv"), TRANSLATIONS_SAVE_CHARACTERS_TO_CSV) + popup.add_icon_item(get_theme_icon("FileList", "EditorIcons"), DialogueConstants.translate(&"save_to_csv"), TRANSLATIONS_SAVE_TO_CSV) + popup.add_icon_item(get_theme_icon("AssetLib", "EditorIcons"), DialogueConstants.translate(&"import_from_csv"), TRANSLATIONS_IMPORT_FROM_CSV) + + # Dialog sizes + new_dialog.min_size = Vector2(600, 500) * scale + save_dialog.min_size = Vector2(600, 500) * scale + open_dialog.min_size = Vector2(600, 500) * scale + export_dialog.min_size = Vector2(600, 500) * scale + import_dialog.min_size = Vector2(600, 500) * scale + settings_dialog.min_size = Vector2(1000, 600) * scale + settings_dialog.max_size = Vector2(1000, 600) * scale + find_in_files_dialog.min_size = Vector2(800, 600) * scale + + +### Helpers + + +# Refresh the open menu with the latest files +func build_open_menu() -> void: + var menu = open_button.get_popup() + menu.clear() + menu.add_icon_item(get_theme_icon("Load", "EditorIcons"), DialogueConstants.translate(&"open.open"), OPEN_OPEN) + menu.add_separator() + + var recent_files = DialogueSettings.get_recent_files() + if recent_files.size() == 0: + menu.add_item(DialogueConstants.translate(&"open.no_recent_files")) + menu.set_item_disabled(2, true) + else: + for path in recent_files: + if FileAccess.file_exists(path): + menu.add_icon_item(get_theme_icon("File", "EditorIcons"), path) + + menu.add_separator() + menu.add_item(DialogueConstants.translate(&"open.clear_recent_files"), OPEN_CLEAR) + if menu.id_pressed.is_connected(_on_open_menu_id_pressed): + menu.id_pressed.disconnect(_on_open_menu_id_pressed) + menu.id_pressed.connect(_on_open_menu_id_pressed) + + +# Get the last place a CSV, etc was exported +func get_last_export_path(extension: String) -> String: + var filename = current_file_path.get_file().replace(".dialogue", "." + extension) + return DialogueSettings.get_user_value("last_export_path", current_file_path.get_base_dir()) + "/" + filename + + +# Check the current text for errors +func parse() -> void: + # Skip if nothing to parse + if current_file_path == "": return + + var parser = DialogueManagerParser.new() + var errors: Array[Dictionary] = [] + if parser.parse(code_edit.text, current_file_path) != OK: + errors = parser.get_errors() + code_edit.errors = errors + errors_panel.errors = errors + parser.free() + + +func show_build_error_dialog() -> void: + build_error_dialog.dialog_text = DialogueConstants.translate(&"errors_with_build") + build_error_dialog.popup_centered() + + +# Generate translation line IDs for any line that doesn't already have one +func generate_translations_keys() -> void: + randomize() + seed(Time.get_unix_time_from_system()) + + var parser = DialogueManagerParser.new() + + var cursor: Vector2 = code_edit.get_cursor() + var lines: PackedStringArray = code_edit.text.split("\n") + + var key_regex = RegEx.new() + key_regex.compile("\\[ID:(?<key>.*?)\\]") + + # Make list of known keys + var known_keys = {} + for i in range(0, lines.size()): + var line = lines[i] + var found = key_regex.search(line) + if found: + var text = "" + var l = line.replace(found.strings[0], "").strip_edges().strip_edges() + if l.begins_with("- "): + text = parser.extract_response_prompt(l) + elif ":" in l: + text = l.split(":")[1] + else: + text = l + known_keys[found.strings[found.names.get("key")]] = text + + # Add in any that are missing + for i in lines.size(): + var line = lines[i] + var l = line.strip_edges() + + if parser.is_line_empty(l): continue + if parser.is_condition_line(l, true): continue + if parser.is_title_line(l): continue + if parser.is_mutation_line(l): continue + if parser.is_goto_line(l): continue + if parser.is_import_line(l): continue + + if "[ID:" in line: continue + + var key = "t" + str(randi() % 1000000).sha1_text().substr(0, 10) + while key in known_keys: + key = "t" + str(randi() % 1000000).sha1_text().substr(0, 10) + + var text = "" + if l.begins_with("- "): + text = parser.extract_response_prompt(l) + else: + text = l.substr(l.find(":") + 1) + + lines[i] = line.replace(text, text + " [ID:%s]" % key) + known_keys[key] = text + + code_edit.text = "\n".join(lines) + code_edit.set_cursor(cursor) + _on_code_edit_text_changed() + + parser.free() + + +# Add a translation file to the project settings +func add_path_to_project_translations(path: String) -> void: + var translations: PackedStringArray = ProjectSettings.get_setting("internationalization/locale/translations") + if not path in translations: + translations.append(path) + ProjectSettings.save() + + +# Export dialogue and responses to CSV +func export_translations_to_csv(path: String) -> void: + var default_locale: String = DialogueSettings.get_setting("default_csv_locale", "en") + + var file: FileAccess + + # If the file exists, open it first and work out which keys are already in it + var existing_csv: Dictionary = {} + var column_count: int = 2 + var default_locale_column: int = 1 + var character_column: int = -1 + var notes_column: int = -1 + if FileAccess.file_exists(path): + file = FileAccess.open(path, FileAccess.READ) + var is_first_line = true + var line: Array + while !file.eof_reached(): + line = file.get_csv_line() + if is_first_line: + is_first_line = false + column_count = line.size() + for i in range(1, line.size()): + if line[i] == default_locale: + default_locale_column = i + elif line[i] == "_character": + character_column = i + elif line[i] == "_notes": + notes_column = i + + # Make sure the line isn't empty before adding it + if line.size() > 0 and line[0].strip_edges() != "": + existing_csv[line[0]] = line + + # The character column wasn't found in the existing file but the setting is turned on + if character_column == -1 and DialogueSettings.get_setting("include_character_in_translation_exports", false): + character_column = column_count + column_count += 1 + existing_csv["keys"].append("_character") + + # The notes column wasn't found in the existing file but the setting is turned on + if notes_column == -1 and DialogueSettings.get_setting("include_notes_in_translation_exports", false): + notes_column = column_count + column_count += 1 + existing_csv["keys"].append("_notes") + + # Start a new file + file = FileAccess.open(path, FileAccess.WRITE) + + if not FileAccess.file_exists(path): + var headings: PackedStringArray = ["keys", default_locale] + if DialogueSettings.get_setting("include_character_in_translation_exports", false): + character_column = headings.size() + headings.append("_character") + if DialogueSettings.get_setting("include_notes_in_translation_exports", false): + notes_column = headings.size() + headings.append("_notes") + file.store_csv_line(headings) + column_count = headings.size() + + # Write our translations to file + var known_keys: PackedStringArray = [] + + var dialogue: Dictionary = DialogueManagerParser.parse_string(code_edit.text, current_file_path).lines + + # Make a list of stuff that needs to go into the file + var lines_to_save = [] + for key in dialogue.keys(): + var line: Dictionary = dialogue.get(key) + + if not line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: continue + if line.translation_key in known_keys: continue + + known_keys.append(line.translation_key) + + var line_to_save: PackedStringArray = [] + if existing_csv.has(line.translation_key): + line_to_save = existing_csv.get(line.translation_key) + line_to_save.resize(column_count) + existing_csv.erase(line.translation_key) + else: + line_to_save.resize(column_count) + line_to_save[0] = line.translation_key + + line_to_save[default_locale_column] = line.text + if character_column > -1: + line_to_save[character_column] = "(response)" if line.type == DialogueConstants.TYPE_RESPONSE else line.character + if notes_column > -1: + line_to_save[notes_column] = line.notes + + lines_to_save.append(line_to_save) + + # Store lines in the file, starting with anything that already exists that hasn't been touched + for line in existing_csv.values(): + file.store_csv_line(line) + for line in lines_to_save: + file.store_csv_line(line) + + file.close() + + editor_plugin.get_editor_interface().get_resource_filesystem().scan() + editor_plugin.get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", path) + + # Add it to the project l10n settings if it's not already there + var language_code: RegExMatch = RegEx.create_from_string("^[a-z]{2,3}").search(default_locale) + var translation_path: String = path.replace(".csv", ".%s.translation" % language_code.get_string()) + call_deferred("add_path_to_project_translations", translation_path) + + +func export_character_names_to_csv(path: String) -> void: + var file: FileAccess + + # If the file exists, open it first and work out which keys are already in it + var existing_csv = {} + var commas = [] + if FileAccess.file_exists(path): + file = FileAccess.open(path, FileAccess.READ) + var is_first_line = true + var line: Array + while !file.eof_reached(): + line = file.get_csv_line() + if is_first_line: + is_first_line = false + for i in range(2, line.size()): + commas.append("") + # Make sure the line isn't empty before adding it + if line.size() > 0 and line[0].strip_edges() != "": + existing_csv[line[0]] = line + + # Start a new file + file = FileAccess.open(path, FileAccess.WRITE) + + if not file.file_exists(path): + file.store_csv_line(["keys", DialogueSettings.get_setting("default_csv_locale", "en")]) + + # Write our translations to file + var known_keys: PackedStringArray = [] + + var character_names: PackedStringArray = DialogueManagerParser.parse_string(code_edit.text, current_file_path).character_names + + # Make a list of stuff that needs to go into the file + var lines_to_save = [] + for character_name in character_names: + if character_name in known_keys: continue + + known_keys.append(character_name) + + if existing_csv.has(character_name): + var existing_line = existing_csv.get(character_name) + existing_line[1] = character_name + lines_to_save.append(existing_line) + existing_csv.erase(character_name) + else: + lines_to_save.append(PackedStringArray([character_name, character_name] + commas)) + + # Store lines in the file, starting with anything that already exists that hasn't been touched + for line in existing_csv.values(): + file.store_csv_line(line) + for line in lines_to_save: + file.store_csv_line(line) + + file.close() + + editor_plugin.get_editor_interface().get_resource_filesystem().scan() + editor_plugin.get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", path) + + # Add it to the project l10n settings if it's not already there + var translation_path: String = path.replace(".csv", ".en.translation") + call_deferred("add_path_to_project_translations", translation_path) + + +# Import changes back from an exported CSV by matching translation keys +func import_translations_from_csv(path: String) -> void: + var cursor: Vector2 = code_edit.get_cursor() + + if not FileAccess.file_exists(path): return + + # Open the CSV file and build a dictionary of the known keys + var keys: Dictionary = {} + var file: FileAccess = FileAccess.open(path, FileAccess.READ) + var csv_line: Array + while !file.eof_reached(): + csv_line = file.get_csv_line() + if csv_line.size() > 1: + keys[csv_line[0]] = csv_line[1] + + var parser: DialogueManagerParser = DialogueManagerParser.new() + + # Now look over each line in the dialogue and replace the content for matched keys + var lines: PackedStringArray = code_edit.text.split("\n") + var start_index: int = 0 + var end_index: int = 0 + for i in range(0, lines.size()): + var line: String = lines[i] + var translation_key: String = parser.extract_translation(line) + if keys.has(translation_key): + if parser.is_dialogue_line(line): + start_index = 0 + # See if we need to skip over a character name + line = line.replace("\\:", "!ESCAPED_COLON!") + if ": " in line: + start_index = line.find(": ") + 2 + lines[i] = (line.substr(0, start_index) + keys.get(translation_key) + " [ID:" + translation_key + "]").replace("!ESCAPED_COLON!", ":") + + elif parser.is_response_line(line): + start_index = line.find("- ") + 2 + # See if we need to skip over a character name + line = line.replace("\\:", "!ESCAPED_COLON!") + if ": " in line: + start_index = line.find(": ") + 2 + end_index = line.length() + if " =>" in line: + end_index = line.find(" =>") + if " [if " in line: + end_index = line.find(" [if ") + lines[i] = (line.substr(0, start_index) + keys.get(translation_key) + " [ID:" + translation_key + "]" + line.substr(end_index)).replace("!ESCAPED_COLON!", ":") + + code_edit.text = "\n".join(lines) + code_edit.set_cursor(cursor) + + parser.free() + + +func show_search_form(is_enabled: bool) -> void: + if code_edit.last_selected_text: + search_and_replace.input.text = code_edit.last_selected_text + + search_and_replace.visible = is_enabled + search_button.set_pressed_no_signal(is_enabled) + search_and_replace.focus_line_edit() + + +### Signals + + +func _on_editor_settings_changed() -> void: + var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() + code_edit.minimap_draw = editor_settings.get_setting("text_editor/appearance/minimap/show_minimap") + code_edit.minimap_width = editor_settings.get_setting("text_editor/appearance/minimap/minimap_width") + code_edit.scroll_smooth = editor_settings.get_setting("text_editor/behavior/navigation/smooth_scrolling") + + +func _on_open_menu_id_pressed(id: int) -> void: + match id: + OPEN_OPEN: + open_dialog.popup_centered() + OPEN_CLEAR: + DialogueSettings.clear_recent_files() + build_open_menu() + _: + var menu = open_button.get_popup() + var item = menu.get_item_text(menu.get_item_index(id)) + open_file(item) + + +func _on_files_list_file_selected(file_path: String) -> void: + self.current_file_path = file_path + + +func _on_insert_button_menu_id_pressed(id: int) -> void: + match id: + 0: + code_edit.insert_bbcode("[wave amp=25 freq=5]", "[/wave]") + 1: + code_edit.insert_bbcode("[shake rate=20 level=10]", "[/shake]") + 3: + code_edit.insert_bbcode("[wait=1]") + 4: + code_edit.insert_bbcode("[speed=0.2]") + 5: + code_edit.insert_bbcode("[next=auto]") + 6: + code_edit.insert_text("~ title") + 7: + code_edit.insert_text("Nathan: This is Some Dialogue") + 8: + code_edit.insert_text("Nathan: Choose a Response...\n- Option 1\n\tNathan: You chose option 1\n- Option 2\n\tNathan: You chose option 2") + 9: + code_edit.insert_text("% Nathan: This is random line 1.\n% Nathan: This is random line 2.\n%1 Nathan: This is weighted random line 3.") + 10: + code_edit.insert_text("Nathan: [[Hi|Hello|Howdy]]") + 11: + code_edit.insert_text("=> title") + 12: + code_edit.insert_text("=> END") + + +func _on_translations_button_menu_id_pressed(id: int) -> void: + match id: + TRANSLATIONS_GENERATE_LINE_IDS: + generate_translations_keys() + + TRANSLATIONS_SAVE_CHARACTERS_TO_CSV: + translation_source = TranslationSource.CharacterNames + export_dialog.filters = PackedStringArray(["*.csv ; Translation CSV"]) + export_dialog.current_path = get_last_export_path("csv") + export_dialog.popup_centered() + + TRANSLATIONS_SAVE_TO_CSV: + translation_source = TranslationSource.Lines + export_dialog.filters = PackedStringArray(["*.csv ; Translation CSV"]) + export_dialog.current_path = get_last_export_path("csv") + export_dialog.popup_centered() + + TRANSLATIONS_IMPORT_FROM_CSV: + import_dialog.current_path = get_last_export_path("csv") + import_dialog.popup_centered() + + +func _on_export_dialog_file_selected(path: String) -> void: + DialogueSettings.set_user_value("last_export_path", path.get_base_dir()) + match path.get_extension(): + "csv": + match translation_source: + TranslationSource.CharacterNames: + export_character_names_to_csv(path) + TranslationSource.Lines: + export_translations_to_csv(path) + + +func _on_import_dialog_file_selected(path: String) -> void: + DialogueSettings.set_user_value("last_export_path", path.get_base_dir()) + import_translations_from_csv(path) + + +func _on_main_view_theme_changed(): + apply_theme() + + +func _on_main_view_visibility_changed() -> void: + if visible and is_instance_valid(code_edit): + code_edit.grab_focus() + + +func _on_new_button_pressed() -> void: + new_dialog.current_file = "" + new_dialog.popup_centered() + + +func _on_new_dialog_file_selected(path: String) -> void: + new_file(path) + open_file(path) + + +func _on_save_dialog_file_selected(path: String) -> void: + new_file(path, code_edit.text) + open_file(path) + + +func _on_open_button_about_to_popup() -> void: + build_open_menu() + + +func _on_open_dialog_file_selected(path: String) -> void: + open_file(path) + + +func _on_save_all_button_pressed() -> void: + save_files() + + +func _on_find_in_files_button_pressed() -> void: + find_in_files_dialog.popup_centered() + find_in_files.prepare() + + +func _on_code_edit_text_changed() -> void: + title_list.titles = code_edit.get_titles() + + var buffer = open_buffers[current_file_path] + buffer.text = code_edit.text + + files_list.mark_file_as_unsaved(current_file_path, buffer.text != buffer.pristine_text) + save_all_button.disabled = open_buffers.values().filter(func(d): return d.text != d.pristine_text).size() == 0 + + parse_timer.start(1) + + +func _on_code_edit_active_title_change(title: String) -> void: + title_list.select_title(title) + DialogueSettings.set_user_value("run_title", title) + + +func _on_code_edit_caret_changed() -> void: + DialogueSettings.set_caret(current_file_path, code_edit.get_cursor()) + + +func _on_code_edit_error_clicked(line_number: int) -> void: + errors_panel.show_error_for_line_number(line_number) + + +func _on_title_list_title_selected(title: String) -> void: + code_edit.go_to_title(title) + code_edit.grab_focus() + + +func _on_parse_timer_timeout() -> void: + parse_timer.stop() + parse() + + +func _on_errors_panel_error_pressed(line_number: int, column_number: int) -> void: + code_edit.set_caret_line(line_number) + code_edit.set_caret_column(column_number) + code_edit.grab_focus() + + +func _on_search_button_toggled(button_pressed: bool) -> void: + show_search_form(button_pressed) + + +func _on_search_and_replace_open_requested() -> void: + show_search_form(true) + + +func _on_search_and_replace_close_requested() -> void: + search_button.set_pressed_no_signal(false) + search_and_replace.visible = false + code_edit.grab_focus() + + +func _on_settings_button_pressed() -> void: + settings_view.prepare() + settings_dialog.popup_centered() + + +func _on_settings_view_script_button_pressed(path: String) -> void: + settings_dialog.hide() + editor_plugin.get_editor_interface().edit_resource(load(path)) + + +func _on_test_button_pressed() -> void: + save_file(current_file_path) + + if errors_panel.errors.size() > 0: + errors_dialog.popup_centered() + return + + DialogueSettings.set_user_value("is_running_test_scene", true) + DialogueSettings.set_user_value("run_resource_path", current_file_path) + var test_scene_path: String = DialogueSettings.get_setting("custom_test_scene_path", "res://addons/dialogue_manager/test_scene.tscn") + editor_plugin.get_editor_interface().play_custom_scene(test_scene_path) + + +func _on_settings_dialog_confirmed() -> void: + settings_view.apply_settings_changes() + parse() + code_edit.wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY if DialogueSettings.get_setting("wrap_lines", false) else TextEdit.LINE_WRAPPING_NONE + code_edit.grab_focus() + + +func _on_support_button_pressed() -> void: + OS.shell_open("https://patreon.com/nathanhoad") + + +func _on_docs_button_pressed() -> void: + OS.shell_open("https://github.com/nathanhoad/godot_dialogue_manager") + + +func _on_files_list_file_popup_menu_requested(at_position: Vector2) -> void: + files_popup_menu.position = Vector2(get_viewport().position) + files_list.global_position + at_position + files_popup_menu.popup() + + +func _on_files_list_file_middle_clicked(path: String): + close_file(path) + + +func _on_files_popup_menu_about_to_popup() -> void: + files_popup_menu.clear() + + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save"), ITEM_SAVE, KEY_MASK_CTRL | KEY_MASK_ALT | KEY_S) + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save_as"), ITEM_SAVE_AS) + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close"), ITEM_CLOSE, KEY_MASK_CTRL | KEY_W) + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_all"), ITEM_CLOSE_ALL) + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_other_files"), ITEM_CLOSE_OTHERS) + files_popup_menu.add_separator() + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.copy_file_path"), ITEM_COPY_PATH) + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.show_in_filesystem"), ITEM_SHOW_IN_FILESYSTEM) + + +func _on_files_popup_menu_id_pressed(id: int) -> void: + match id: + ITEM_SAVE: + save_file(current_file_path) + ITEM_SAVE_AS: + save_dialog.popup_centered() + ITEM_CLOSE: + close_file(current_file_path) + ITEM_CLOSE_ALL: + for path in open_buffers.keys(): + close_file(path) + ITEM_CLOSE_OTHERS: + for path in open_buffers.keys(): + if path != current_file_path: + close_file(path) + + ITEM_COPY_PATH: + DisplayServer.clipboard_set(current_file_path) + ITEM_SHOW_IN_FILESYSTEM: + show_file_in_filesystem(current_file_path) + + +func _on_code_edit_external_file_requested(path: String, title: String) -> void: + open_file(path) + if title != "": + code_edit.go_to_title(title) + else: + code_edit.set_caret_line(0) + + +func _on_close_confirmation_dialog_confirmed() -> void: + save_file(current_file_path) + remove_file_from_open_buffers(current_file_path) + + +func _on_close_confirmation_dialog_custom_action(action: StringName) -> void: + if action == "discard": + remove_file_from_open_buffers(current_file_path) + close_confirmation_dialog.hide() + + +func _on_find_in_files_result_selected(path: String, cursor: Vector2, length: int) -> void: + open_file(path) + code_edit.select(cursor.y, cursor.x, cursor.y, cursor.x + length) diff --git a/addons/dialogue_manager/views/main_view.tscn b/addons/dialogue_manager/views/main_view.tscn new file mode 100644 index 0000000..d57bdf9 --- /dev/null +++ b/addons/dialogue_manager/views/main_view.tscn @@ -0,0 +1,334 @@ +[gd_scene load_steps=14 format=3 uid="uid://cbuf1q3xsse3q"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/views/main_view.gd" id="1_h6qfq"] +[ext_resource type="PackedScene" uid="uid://civ6shmka5e8u" path="res://addons/dialogue_manager/components/code_edit.tscn" id="2_f73fm"] +[ext_resource type="PackedScene" uid="uid://dnufpcdrreva3" path="res://addons/dialogue_manager/components/files_list.tscn" id="2_npj2k"] +[ext_resource type="PackedScene" uid="uid://ctns6ouwwd68i" path="res://addons/dialogue_manager/components/title_list.tscn" id="2_onb4i"] +[ext_resource type="PackedScene" uid="uid://co8yl23idiwbi" path="res://addons/dialogue_manager/components/update_button.tscn" id="2_ph3vs"] +[ext_resource type="PackedScene" uid="uid://gr8nakpbrhby" path="res://addons/dialogue_manager/components/search_and_replace.tscn" id="6_ylh0t"] +[ext_resource type="PackedScene" uid="uid://cs8pwrxr5vxix" path="res://addons/dialogue_manager/components/errors_panel.tscn" id="7_5cvl4"] +[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit_syntax_highlighter.gd" id="7_necsa"] +[ext_resource type="PackedScene" uid="uid://cpg4lg1r3ff6m" path="res://addons/dialogue_manager/views/settings_view.tscn" id="9_8bf36"] +[ext_resource type="PackedScene" uid="uid://0n7hwviyyly4" path="res://addons/dialogue_manager/components/find_in_files.tscn" id="10_yold3"] + +[sub_resource type="Image" id="Image_xvtti"] +data = { +"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), +"format": "RGBA8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id="ImageTexture_fguub"] +image = SubResource("Image_xvtti") + +[sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_dvnxt"] +script = ExtResource("7_necsa") + +[node name="MainView" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("1_h6qfq") + +[node name="ParseTimer" type="Timer" parent="."] + +[node name="Margin" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_vertical = 3 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_bottom = 5 +metadata/_edit_layout_mode = 1 + +[node name="Content" type="HSplitContainer" parent="Margin"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +dragger_visibility = 1 + +[node name="SidePanel" type="VBoxContainer" parent="Margin/Content"] +custom_minimum_size = Vector2(150, 0) +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Toolbar" type="HBoxContainer" parent="Margin/Content/SidePanel"] +layout_mode = 2 + +[node name="NewButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Start a new file" +flat = true + +[node name="OpenButton" type="MenuButton" parent="Margin/Content/SidePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Open a file" + +[node name="SaveAllButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +disabled = true +flat = true + +[node name="FindInFilesButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +flat = true + +[node name="Bookmarks" type="VSplitContainer" parent="Margin/Content/SidePanel"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="FilesList" parent="Margin/Content/SidePanel/Bookmarks" instance=ExtResource("2_npj2k")] +unique_name_in_owner = true +visible = false +layout_mode = 2 +size_flags_vertical = 3 + +[node name="FilesPopupMenu" type="PopupMenu" parent="Margin/Content/SidePanel/Bookmarks/FilesList"] +unique_name_in_owner = true + +[node name="TitleList" parent="Margin/Content/SidePanel/Bookmarks" instance=ExtResource("2_onb4i")] +unique_name_in_owner = true +visible = false +layout_mode = 2 + +[node name="CodePanel" type="VBoxContainer" parent="Margin/Content"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 4.0 + +[node name="Toolbar" type="HBoxContainer" parent="Margin/Content/CodePanel"] +layout_mode = 2 + +[node name="InsertButton" type="MenuButton" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +disabled = true +text = "Insert" + +[node name="TranslationsButton" type="MenuButton" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +disabled = true +text = "Translations" +item_count = 6 +popup/item_0/text = "Generate line IDs" +popup/item_0/icon = SubResource("ImageTexture_fguub") +popup/item_0/id = 0 +popup/item_1/text = "" +popup/item_1/id = -1 +popup/item_1/separator = true +popup/item_2/text = "Save to CSV..." +popup/item_2/icon = SubResource("ImageTexture_fguub") +popup/item_2/id = 2 +popup/item_3/text = "Import changes from CSV..." +popup/item_3/icon = SubResource("ImageTexture_fguub") +popup/item_3/id = 3 +popup/item_4/text = "" +popup/item_4/id = -1 +popup/item_4/separator = true +popup/item_5/text = "Save to PO..." +popup/item_5/icon = SubResource("ImageTexture_fguub") +popup/item_5/id = 5 + +[node name="Separator" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] +layout_mode = 2 + +[node name="SearchButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Search for text" +disabled = true +toggle_mode = true +flat = true + +[node name="TestButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Test dialogue" +disabled = true +flat = true + +[node name="Separator3" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] +layout_mode = 2 + +[node name="SettingsButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Settings" +flat = true + +[node name="Spacer2" type="Control" parent="Margin/Content/CodePanel/Toolbar"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="SupportButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +flat = true + +[node name="Separator4" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] +layout_mode = 2 + +[node name="DocsButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Docs" +flat = true + +[node name="VersionLabel" type="Label" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +modulate = Color(1, 1, 1, 0.490196) +layout_mode = 2 +text = "v2.19.0" +vertical_alignment = 1 + +[node name="UpdateButton" parent="Margin/Content/CodePanel/Toolbar" instance=ExtResource("2_ph3vs")] +unique_name_in_owner = true +layout_mode = 2 + +[node name="SearchAndReplace" parent="Margin/Content/CodePanel" instance=ExtResource("6_ylh0t")] +unique_name_in_owner = true +layout_mode = 2 + +[node name="CodeEdit" parent="Margin/Content/CodePanel" instance=ExtResource("2_f73fm")] +unique_name_in_owner = true +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_colors/bookmark_color = Color(1, 0.333333, 0.333333, 1) +text = "" +syntax_highlighter = SubResource("SyntaxHighlighter_dvnxt") + +[node name="ErrorsPanel" parent="Margin/Content/CodePanel" instance=ExtResource("7_5cvl4")] +unique_name_in_owner = true +layout_mode = 2 + +[node name="NewDialog" type="FileDialog" parent="."] +size = Vector2i(600, 500) +min_size = Vector2i(600, 500) +dialog_hide_on_ok = true +filters = PackedStringArray("*.dialogue ; Dialogue") + +[node name="SaveDialog" type="FileDialog" parent="."] +size = Vector2i(600, 500) +min_size = Vector2i(600, 500) +dialog_hide_on_ok = true +filters = PackedStringArray("*.dialogue ; Dialogue") + +[node name="OpenDialog" type="FileDialog" parent="."] +title = "Open a File" +size = Vector2i(600, 500) +min_size = Vector2i(600, 500) +ok_button_text = "Open" +dialog_hide_on_ok = true +file_mode = 0 +filters = PackedStringArray("*.dialogue ; Dialogue") + +[node name="ExportDialog" type="FileDialog" parent="."] +size = Vector2i(600, 500) +min_size = Vector2i(600, 500) + +[node name="ImportDialog" type="FileDialog" parent="."] +title = "Open a File" +size = Vector2i(600, 500) +min_size = Vector2i(600, 500) +ok_button_text = "Open" +file_mode = 0 +filters = PackedStringArray("*.csv ; Translation CSV") + +[node name="ErrorsDialog" type="AcceptDialog" parent="."] +title = "Error" +dialog_text = "You have errors in your script. Fix them and then try again." + +[node name="SettingsDialog" type="AcceptDialog" parent="."] +title = "Settings" +size = Vector2i(834, 600) +unresizable = true +min_size = Vector2i(600, 600) +ok_button_text = "Done" + +[node name="SettingsView" parent="SettingsDialog" instance=ExtResource("9_8bf36")] +offset_left = 8.0 +offset_top = 8.0 +offset_right = -8.0 +offset_bottom = -49.0 + +[node name="BuildErrorDialog" type="AcceptDialog" parent="."] +title = "Errors" +dialog_text = "You need to fix dialogue errors before you can run your game." + +[node name="CloseConfirmationDialog" type="ConfirmationDialog" parent="."] +title = "Unsaved changes" +ok_button_text = "Save changes" + +[node name="UpdatedDialog" type="AcceptDialog" parent="."] +title = "Updated" +size = Vector2i(191, 100) +dialog_text = "You're now up to date!" + +[node name="FindInFilesDialog" type="AcceptDialog" parent="."] +title = "Find in files" +size = Vector2i(416, 457) +ok_button_text = "Done" + +[node name="FindInFiles" parent="FindInFilesDialog" node_paths=PackedStringArray("main_view", "code_edit") instance=ExtResource("10_yold3")] +custom_minimum_size = Vector2(400, 400) +offset_left = 8.0 +offset_top = 8.0 +offset_right = -8.0 +offset_bottom = -49.0 +main_view = NodePath("../..") +code_edit = NodePath("../../Margin/Content/CodePanel/CodeEdit") + +[connection signal="theme_changed" from="." to="." method="_on_main_view_theme_changed"] +[connection signal="visibility_changed" from="." to="." method="_on_main_view_visibility_changed"] +[connection signal="timeout" from="ParseTimer" to="." method="_on_parse_timer_timeout"] +[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/NewButton" to="." method="_on_new_button_pressed"] +[connection signal="about_to_popup" from="Margin/Content/SidePanel/Toolbar/OpenButton" to="." method="_on_open_button_about_to_popup"] +[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/SaveAllButton" to="." method="_on_save_all_button_pressed"] +[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/FindInFilesButton" to="." method="_on_find_in_files_button_pressed"] +[connection signal="file_middle_clicked" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_middle_clicked"] +[connection signal="file_popup_menu_requested" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_popup_menu_requested"] +[connection signal="file_selected" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_selected"] +[connection signal="about_to_popup" from="Margin/Content/SidePanel/Bookmarks/FilesList/FilesPopupMenu" to="." method="_on_files_popup_menu_about_to_popup"] +[connection signal="id_pressed" from="Margin/Content/SidePanel/Bookmarks/FilesList/FilesPopupMenu" to="." method="_on_files_popup_menu_id_pressed"] +[connection signal="title_selected" from="Margin/Content/SidePanel/Bookmarks/TitleList" to="." method="_on_title_list_title_selected"] +[connection signal="toggled" from="Margin/Content/CodePanel/Toolbar/SearchButton" to="." method="_on_search_button_toggled"] +[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/TestButton" to="." method="_on_test_button_pressed"] +[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/SettingsButton" to="." method="_on_settings_button_pressed"] +[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/SupportButton" to="." method="_on_support_button_pressed"] +[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/DocsButton" to="." method="_on_docs_button_pressed"] +[connection signal="close_requested" from="Margin/Content/CodePanel/SearchAndReplace" to="." method="_on_search_and_replace_close_requested"] +[connection signal="open_requested" from="Margin/Content/CodePanel/SearchAndReplace" to="." method="_on_search_and_replace_open_requested"] +[connection signal="active_title_change" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_active_title_change"] +[connection signal="caret_changed" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_caret_changed"] +[connection signal="error_clicked" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_error_clicked"] +[connection signal="external_file_requested" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_external_file_requested"] +[connection signal="text_changed" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_text_changed"] +[connection signal="error_pressed" from="Margin/Content/CodePanel/ErrorsPanel" to="." method="_on_errors_panel_error_pressed"] +[connection signal="file_selected" from="NewDialog" to="." method="_on_new_dialog_file_selected"] +[connection signal="file_selected" from="SaveDialog" to="." method="_on_save_dialog_file_selected"] +[connection signal="file_selected" from="OpenDialog" to="." method="_on_open_dialog_file_selected"] +[connection signal="file_selected" from="ExportDialog" to="." method="_on_export_dialog_file_selected"] +[connection signal="file_selected" from="ImportDialog" to="." method="_on_import_dialog_file_selected"] +[connection signal="confirmed" from="SettingsDialog" to="." method="_on_settings_dialog_confirmed"] +[connection signal="script_button_pressed" from="SettingsDialog/SettingsView" to="." method="_on_settings_view_script_button_pressed"] +[connection signal="confirmed" from="CloseConfirmationDialog" to="." method="_on_close_confirmation_dialog_confirmed"] +[connection signal="custom_action" from="CloseConfirmationDialog" to="." method="_on_close_confirmation_dialog_custom_action"] +[connection signal="result_selected" from="FindInFilesDialog/FindInFiles" to="." method="_on_find_in_files_result_selected"] diff --git a/addons/dialogue_manager/views/settings_view.gd b/addons/dialogue_manager/views/settings_view.gd new file mode 100644 index 0000000..8ab4e95 --- /dev/null +++ b/addons/dialogue_manager/views/settings_view.gd @@ -0,0 +1,280 @@ +@tool +extends TabContainer + + +signal script_button_pressed(path: String) + + +const DialogueConstants = preload("../constants.gd") +const DialogueSettings = preload("../settings.gd") + + +enum PathTarget { + CustomTestScene, + Balloon +} + + +# Editor +@onready var new_template_button: CheckBox = $Editor/NewTemplateButton +@onready var characters_translations_button: CheckBox = $Editor/CharactersTranslationsButton +@onready var wrap_lines_button: Button = $Editor/WrapLinesButton +@onready var default_csv_locale: LineEdit = $Editor/DefaultCSVLocale + +# Runtime +@onready var include_all_responses_button: CheckBox = $Runtime/IncludeAllResponsesButton +@onready var ignore_missing_state_values: CheckBox = $Runtime/IgnoreMissingStateValues +@onready var balloon_path_input: LineEdit = $Runtime/CustomBalloon/BalloonPath +@onready var revert_balloon_button: Button = $Runtime/CustomBalloon/RevertBalloonPath +@onready var load_balloon_button: Button = $Runtime/CustomBalloon/LoadBalloonPath +@onready var states_title: Label = $Runtime/StatesTitle +@onready var globals_list: Tree = $Runtime/GlobalsList + +# Advanced +@onready var check_for_updates: CheckBox = $Advanced/CheckForUpdates +@onready var include_characters_in_translations: CheckBox = $Advanced/IncludeCharactersInTranslations +@onready var include_notes_in_translations: CheckBox = $Advanced/IncludeNotesInTranslations +@onready var open_in_external_editor_button: CheckBox = $Advanced/OpenInExternalEditorButton +@onready var test_scene_path_input: LineEdit = $Advanced/CustomTestScene/TestScenePath +@onready var revert_test_scene_button: Button = $Advanced/CustomTestScene/RevertTestScene +@onready var load_test_scene_button: Button = $Advanced/CustomTestScene/LoadTestScene +@onready var custom_test_scene_file_dialog: FileDialog = $CustomTestSceneFileDialog +@onready var create_lines_for_response_characters: CheckBox = $Advanced/CreateLinesForResponseCharacters +@onready var missing_translations_button: CheckBox = $Advanced/MissingTranslationsButton + +var editor_plugin: EditorPlugin +var all_globals: Dictionary = {} +var enabled_globals: Array = [] +var path_target: PathTarget = PathTarget.CustomTestScene + +var _default_test_scene_path: String = preload("../test_scene.tscn").resource_path + +var _recompile_if_changed_settings: Dictionary + + +func _ready() -> void: + new_template_button.text = DialogueConstants.translate(&"settings.new_template") + $Editor/MissingTranslationsHint.text = DialogueConstants.translate(&"settings.missing_keys_hint") + characters_translations_button.text = DialogueConstants.translate(&"settings.characters_translations") + wrap_lines_button.text = DialogueConstants.translate(&"settings.wrap_long_lines") + $Editor/DefaultCSVLocaleLabel.text = DialogueConstants.translate(&"settings.default_csv_locale") + + include_all_responses_button.text = DialogueConstants.translate(&"settings.include_failed_responses") + ignore_missing_state_values.text = DialogueConstants.translate(&"settings.ignore_missing_state_values") + $Runtime/CustomBalloonLabel.text = DialogueConstants.translate(&"settings.default_balloon_hint") + states_title.text = DialogueConstants.translate(&"settings.states_shortcuts") + $Runtime/StatesMessage.text = DialogueConstants.translate(&"settings.states_message") + $Runtime/StatesHint.text = DialogueConstants.translate(&"settings.states_hint") + + check_for_updates.text = DialogueConstants.translate(&"settings.check_for_updates") + include_characters_in_translations.text = DialogueConstants.translate(&"settings.include_characters_in_translations") + include_notes_in_translations.text = DialogueConstants.translate(&"settings.include_notes_in_translations") + open_in_external_editor_button.text = DialogueConstants.translate(&"settings.open_in_external_editor") + $Advanced/ExternalWarning.text = DialogueConstants.translate(&"settings.external_editor_warning") + $Advanced/CustomTestSceneLabel.text = DialogueConstants.translate(&"settings.custom_test_scene") + $Advanced/RecompileWarning.text = DialogueConstants.translate(&"settings.recompile_warning") + missing_translations_button.text = DialogueConstants.translate(&"settings.missing_keys") + create_lines_for_response_characters.text = DialogueConstants.translate(&"settings.create_lines_for_responses_with_characters") + + current_tab = 0 + + +func prepare() -> void: + _recompile_if_changed_settings = _get_settings_that_require_recompilation() + + test_scene_path_input.placeholder_text = DialogueSettings.get_setting("custom_test_scene_path", _default_test_scene_path) + revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path + revert_test_scene_button.icon = get_theme_icon("RotateLeft", "EditorIcons") + revert_test_scene_button.tooltip_text = DialogueConstants.translate(&"settings.revert_to_default_test_scene") + load_test_scene_button.icon = get_theme_icon("Load", "EditorIcons") + + var balloon_path: String = DialogueSettings.get_setting("balloon_path", "") + if not FileAccess.file_exists(balloon_path): + DialogueSettings.set_setting("balloon_path", "") + balloon_path = "" + balloon_path_input.placeholder_text = balloon_path if balloon_path != "" else DialogueConstants.translate(&"settings.default_balloon_path") + revert_balloon_button.visible = balloon_path != "" + revert_balloon_button.icon = get_theme_icon("RotateLeft", "EditorIcons") + revert_balloon_button.tooltip_text = DialogueConstants.translate(&"settings.revert_to_default_balloon") + load_balloon_button.icon = get_theme_icon("Load", "EditorIcons") + + var scale: float = editor_plugin.get_editor_interface().get_editor_scale() + custom_test_scene_file_dialog.min_size = Vector2(600, 500) * scale + + states_title.add_theme_font_override("font", get_theme_font("bold", "EditorFonts")) + + check_for_updates.set_pressed_no_signal(DialogueSettings.get_user_value("check_for_updates", true)) + characters_translations_button.set_pressed_no_signal(DialogueSettings.get_setting("export_characters_in_translation", true)) + wrap_lines_button.set_pressed_no_signal(DialogueSettings.get_setting("wrap_lines", false)) + include_all_responses_button.set_pressed_no_signal(DialogueSettings.get_setting("include_all_responses", false)) + ignore_missing_state_values.set_pressed_no_signal(DialogueSettings.get_setting("ignore_missing_state_values", false)) + new_template_button.set_pressed_no_signal(DialogueSettings.get_setting("new_with_template", true)) + default_csv_locale.text = DialogueSettings.get_setting("default_csv_locale", "en") + + missing_translations_button.set_pressed_no_signal(DialogueSettings.get_setting("missing_translations_are_errors", false)) + create_lines_for_response_characters.set_pressed_no_signal(DialogueSettings.get_setting("create_lines_for_responses_with_characters", true)) + + include_characters_in_translations.set_pressed_no_signal(DialogueSettings.get_setting("include_character_in_translation_exports", false)) + include_notes_in_translations.set_pressed_no_signal(DialogueSettings.get_setting("include_notes_in_translation_exports", false)) + open_in_external_editor_button.set_pressed_no_signal(DialogueSettings.get_user_value("open_in_external_editor", false)) + + var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() + var external_editor: String = editor_settings.get_setting("text_editor/external/exec_path") + var use_external_editor: bool = editor_settings.get_setting("text_editor/external/use_external_editor") and external_editor != "" + if not use_external_editor: + open_in_external_editor_button.hide() + $Advanced/ExternalWarning.hide() + $Advanced/ExternalSeparator.hide() + + var project = ConfigFile.new() + var err = project.load("res://project.godot") + assert(err == OK, "Could not find the project file") + + all_globals.clear() + if project.has_section("autoload"): + for key in project.get_section_keys("autoload"): + if key != "DialogueManager": + all_globals[key] = project.get_value("autoload", key) + + enabled_globals = DialogueSettings.get_setting("states", []).duplicate() + globals_list.clear() + var root = globals_list.create_item() + for name in all_globals.keys(): + var item: TreeItem = globals_list.create_item(root) + item.set_cell_mode(0, TreeItem.CELL_MODE_CHECK) + item.set_checked(0, name in enabled_globals) + item.set_text(0, name) + item.add_button(1, get_theme_icon("Edit", "EditorIcons")) + item.set_text(2, all_globals.get(name, "").replace("*res://", "res://")) + + globals_list.set_column_expand(0, false) + globals_list.set_column_custom_minimum_width(0, 250) + globals_list.set_column_expand(1, false) + globals_list.set_column_custom_minimum_width(1, 40) + globals_list.set_column_titles_visible(true) + globals_list.set_column_title(0, DialogueConstants.translate(&"settings.autoload")) + globals_list.set_column_title(1, "") + globals_list.set_column_title(2, DialogueConstants.translate(&"settings.path")) + + +func apply_settings_changes() -> void: + if _recompile_if_changed_settings != _get_settings_that_require_recompilation(): + Engine.get_meta("DialogueCache").reimport_files() + + +func _get_settings_that_require_recompilation() -> Dictionary: + return DialogueSettings.get_settings([ + "missing_translations_are_errors", + "create_lines_for_responses_with_characters" + ]) + + +### Signals + + +func _on_missing_translations_button_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("missing_translations_are_errors", toggled_on) + + +func _on_characters_translations_button_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("export_characters_in_translation", toggled_on) + + +func _on_wrap_lines_button_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("wrap_lines", toggled_on) + + +func _on_include_all_responses_button_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("include_all_responses", toggled_on) + + +func _on_globals_list_item_selected() -> void: + var item = globals_list.get_selected() + var is_checked = not item.is_checked(0) + item.set_checked(0, is_checked) + + if is_checked: + enabled_globals.append(item.get_text(0)) + else: + enabled_globals.erase(item.get_text(0)) + + DialogueSettings.set_setting("states", enabled_globals) + + +func _on_globals_list_button_clicked(item: TreeItem, column: int, id: int, mouse_button_index: int) -> void: + emit_signal("script_button_pressed", item.get_text(2)) + + +func _on_sample_template_toggled(toggled_on): + DialogueSettings.set_setting("new_with_template", toggled_on) + + +func _on_revert_test_scene_pressed() -> void: + DialogueSettings.set_setting("custom_test_scene_path", _default_test_scene_path) + test_scene_path_input.placeholder_text = _default_test_scene_path + revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path + + +func _on_load_test_scene_pressed() -> void: + path_target = PathTarget.CustomTestScene + custom_test_scene_file_dialog.popup_centered() + + +func _on_custom_test_scene_file_dialog_file_selected(path: String) -> void: + match path_target: + PathTarget.CustomTestScene: + # Check that the test scene is a subclass of BaseDialogueTestScene + var test_scene: PackedScene = load(path) + if test_scene and test_scene.instantiate() is BaseDialogueTestScene: + DialogueSettings.set_setting("custom_test_scene_path", path) + test_scene_path_input.placeholder_text = path + revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path + else: + var accept: AcceptDialog = AcceptDialog.new() + accept.dialog_text = DialogueConstants.translate(&"settings.invalid_test_scene").format({ path = path }) + add_child(accept) + accept.popup_centered.call_deferred() + + PathTarget.Balloon: + DialogueSettings.set_setting("balloon_path", path) + balloon_path_input.placeholder_text = path + revert_balloon_button.visible = balloon_path_input.placeholder_text != "" + + +func _on_ignore_missing_state_values_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("ignore_missing_state_values", toggled_on) + + +func _on_default_csv_locale_text_changed(new_text: String) -> void: + DialogueSettings.set_setting("default_csv_locale", new_text) + + +func _on_revert_balloon_path_pressed() -> void: + DialogueSettings.set_setting("balloon_path", "") + balloon_path_input.placeholder_text = DialogueConstants.translate(&"settings.default_balloon_path") + revert_balloon_button.visible = DialogueSettings.get_setting("balloon_path", "") != "" + + +func _on_load_balloon_path_pressed() -> void: + path_target = PathTarget.Balloon + custom_test_scene_file_dialog.popup_centered() + + +func _on_create_lines_for_response_characters_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("create_lines_for_responses_with_characters", toggled_on) + + +func _on_open_in_external_editor_button_toggled(toggled_on: bool) -> void: + DialogueSettings.set_user_value("open_in_external_editor", toggled_on) + + +func _on_include_characters_in_translations_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("include_character_in_translation_exports", toggled_on) + + +func _on_include_notes_in_translations_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("include_notes_in_translation_exports", toggled_on) + + +func _on_keep_up_to_date_toggled(toggled_on: bool) -> void: + DialogueSettings.set_user_value("check_for_updates", toggled_on) diff --git a/addons/dialogue_manager/views/settings_view.tscn b/addons/dialogue_manager/views/settings_view.tscn new file mode 100644 index 0000000..09df0a2 --- /dev/null +++ b/addons/dialogue_manager/views/settings_view.tscn @@ -0,0 +1,221 @@ +[gd_scene load_steps=3 format=3 uid="uid://cpg4lg1r3ff6m"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/views/settings_view.gd" id="1_06uxa"] + +[sub_resource type="Theme" id="Theme_3a8rc"] +HSeparator/constants/separation = 20 + +[node name="SettingsView" type="TabContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = -206.0 +offset_bottom = -345.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme = SubResource("Theme_3a8rc") +current_tab = 2 +script = ExtResource("1_06uxa") + +[node name="Editor" type="VBoxContainer" parent="."] +visible = false +layout_mode = 2 + +[node name="NewTemplateButton" type="CheckBox" parent="Editor"] +layout_mode = 2 +button_pressed = true +text = "New dialogue files will start with template text" + +[node name="MissingTranslationsHint" type="Label" parent="Editor"] +modulate = Color(1, 1, 1, 0.501961) +custom_minimum_size = Vector2(10, 0) +layout_mode = 2 +text = "If you are using static translation keys then having this enabled will help you find any lines that you haven't added a key to yet." +autowrap_mode = 3 + +[node name="CharactersTranslationsButton" type="CheckBox" parent="Editor"] +layout_mode = 2 +button_pressed = true +text = "Export character names in translation files" + +[node name="WrapLinesButton" type="CheckBox" parent="Editor"] +layout_mode = 2 +button_pressed = true +text = "Wrap long lines" + +[node name="HSeparator" type="HSeparator" parent="Editor"] +layout_mode = 2 + +[node name="DefaultCSVLocaleLabel" type="Label" parent="Editor"] +layout_mode = 2 +text = "Default CSV Locale" + +[node name="DefaultCSVLocale" type="LineEdit" parent="Editor"] +layout_mode = 2 + +[node name="Runtime" type="VBoxContainer" parent="."] +visible = false +layout_mode = 2 + +[node name="IncludeAllResponsesButton" type="CheckBox" parent="Runtime"] +layout_mode = 2 +text = "Include responses with failed conditions" + +[node name="IgnoreMissingStateValues" type="CheckBox" parent="Runtime"] +layout_mode = 2 +text = "Skip over missing state value errors (not recommended)" + +[node name="HSeparator" type="HSeparator" parent="Runtime"] +layout_mode = 2 + +[node name="CustomBalloonLabel" type="Label" parent="Runtime"] +layout_mode = 2 +text = "Custom balloon to use when calling \"DialogueManager.show_balloon()\"" + +[node name="CustomBalloon" type="HBoxContainer" parent="Runtime"] +layout_mode = 2 + +[node name="BalloonPath" type="LineEdit" parent="Runtime/CustomBalloon"] +layout_mode = 2 +size_flags_horizontal = 3 +focus_mode = 0 +editable = false +shortcut_keys_enabled = false +middle_mouse_paste_enabled = false + +[node name="RevertBalloonPath" type="Button" parent="Runtime/CustomBalloon"] +visible = false +layout_mode = 2 +tooltip_text = "Revert to default test scene" +flat = true + +[node name="LoadBalloonPath" type="Button" parent="Runtime/CustomBalloon"] +layout_mode = 2 + +[node name="HSeparator2" type="HSeparator" parent="Runtime"] +layout_mode = 2 + +[node name="StatesTitle" type="Label" parent="Runtime"] +layout_mode = 2 +text = "State Shortcuts" + +[node name="StatesMessage" type="Label" parent="Runtime"] +layout_mode = 2 +text = "If an autoload is enabled here you can refer to its properties and methods without having to use its name." + +[node name="StatesHint" type="Label" parent="Runtime"] +modulate = Color(1, 1, 1, 0.501961) +custom_minimum_size = Vector2(10, 0) +layout_mode = 2 +text = "ie. Instead of \"SomeState.some_property\" you could just use \"some_property\"" +autowrap_mode = 3 + +[node name="GlobalsList" type="Tree" parent="Runtime"] +layout_mode = 2 +size_flags_vertical = 3 +columns = 3 +column_titles_visible = true +allow_reselect = true +hide_folding = true +hide_root = true +select_mode = 1 + +[node name="Advanced" type="VBoxContainer" parent="."] +layout_mode = 2 + +[node name="CheckForUpdates" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Check for updates" + +[node name="HSeparator" type="HSeparator" parent="Advanced"] +layout_mode = 2 + +[node name="IncludeCharactersInTranslations" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Include character names in translation exports" + +[node name="IncludeNotesInTranslations" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Include notes (## comments) in translation exports" + +[node name="ExternalSeparator" type="HSeparator" parent="Advanced"] +layout_mode = 2 + +[node name="OpenInExternalEditorButton" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Open dialogue files in external editor" + +[node name="ExternalWarning" type="Label" parent="Advanced"] +layout_mode = 2 +text = "Note: Syntax highlighting and detailed error checking are not supported in external editors." + +[node name="HSeparator3" type="HSeparator" parent="Advanced"] +layout_mode = 2 + +[node name="CustomTestSceneLabel" type="Label" parent="Advanced"] +layout_mode = 2 +text = "Custom test scene (must extend BaseDialogueTestScene)" + +[node name="CustomTestScene" type="HBoxContainer" parent="Advanced"] +layout_mode = 2 + +[node name="TestScenePath" type="LineEdit" parent="Advanced/CustomTestScene"] +layout_mode = 2 +size_flags_horizontal = 3 +focus_mode = 0 +placeholder_text = "res://addons/dialogue_manager/test_scene.tscn" +editable = false +shortcut_keys_enabled = false +middle_mouse_paste_enabled = false + +[node name="RevertTestScene" type="Button" parent="Advanced/CustomTestScene"] +visible = false +layout_mode = 2 +tooltip_text = "Revert to default test scene" +flat = true + +[node name="LoadTestScene" type="Button" parent="Advanced/CustomTestScene"] +layout_mode = 2 + +[node name="HSeparator4" type="HSeparator" parent="Advanced"] +layout_mode = 2 + +[node name="RecompileWarning" type="Label" parent="Advanced"] +layout_mode = 2 +text = "Changing these settings will force a recompile of all dialogue. Only change them if you know what you are doing." + +[node name="MissingTranslationsButton" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Treat missing translation keys as errors" + +[node name="CreateLinesForResponseCharacters" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Create child dialogue line for responses with character names in them" + +[node name="CustomTestSceneFileDialog" type="FileDialog" parent="."] +title = "Open a File" +ok_button_text = "Open" +file_mode = 0 +filters = PackedStringArray("*.tscn ; Scene") + +[connection signal="toggled" from="Editor/NewTemplateButton" to="." method="_on_sample_template_toggled"] +[connection signal="toggled" from="Editor/CharactersTranslationsButton" to="." method="_on_characters_translations_button_toggled"] +[connection signal="toggled" from="Editor/WrapLinesButton" to="." method="_on_wrap_lines_button_toggled"] +[connection signal="text_changed" from="Editor/DefaultCSVLocale" to="." method="_on_default_csv_locale_text_changed"] +[connection signal="toggled" from="Runtime/IncludeAllResponsesButton" to="." method="_on_include_all_responses_button_toggled"] +[connection signal="toggled" from="Runtime/IgnoreMissingStateValues" to="." method="_on_ignore_missing_state_values_toggled"] +[connection signal="pressed" from="Runtime/CustomBalloon/RevertBalloonPath" to="." method="_on_revert_balloon_path_pressed"] +[connection signal="pressed" from="Runtime/CustomBalloon/LoadBalloonPath" to="." method="_on_load_balloon_path_pressed"] +[connection signal="button_clicked" from="Runtime/GlobalsList" to="." method="_on_globals_list_button_clicked"] +[connection signal="item_selected" from="Runtime/GlobalsList" to="." method="_on_globals_list_item_selected"] +[connection signal="toggled" from="Advanced/CheckForUpdates" to="." method="_on_keep_up_to_date_toggled"] +[connection signal="toggled" from="Advanced/IncludeCharactersInTranslations" to="." method="_on_include_characters_in_translations_toggled"] +[connection signal="toggled" from="Advanced/IncludeNotesInTranslations" to="." method="_on_include_notes_in_translations_toggled"] +[connection signal="toggled" from="Advanced/OpenInExternalEditorButton" to="." method="_on_open_in_external_editor_button_toggled"] +[connection signal="pressed" from="Advanced/CustomTestScene/RevertTestScene" to="." method="_on_revert_test_scene_pressed"] +[connection signal="pressed" from="Advanced/CustomTestScene/LoadTestScene" to="." method="_on_load_test_scene_pressed"] +[connection signal="toggled" from="Advanced/MissingTranslationsButton" to="." method="_on_missing_translations_button_toggled"] +[connection signal="toggled" from="Advanced/CreateLinesForResponseCharacters" to="." method="_on_create_lines_for_response_characters_toggled"] +[connection signal="file_selected" from="CustomTestSceneFileDialog" to="." method="_on_custom_test_scene_file_dialog_file_selected"] diff --git a/project.godot b/project.godot index b834fbd..5f834c1 100644 --- a/project.godot +++ b/project.godot @@ -15,6 +15,11 @@ run/main_scene="res://src/main/main.tscn" config/features=PackedStringArray("4.2", "GL Compatibility") config/icon="res://icon.svg" +[autoload] + +DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd" +PlayerState="*res://src/autoloads/player_state.gd" + [display] window/size/viewport_width=256 @@ -24,8 +29,26 @@ window/size/window_height_override=720 window/stretch/mode="viewport" window/stretch/scale_mode="integer" +[editor_plugins] + +enabled=PackedStringArray("res://addons/dialogue_manager/plugin.cfg") + [input] +ui_accept={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194309,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194310,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":32,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) +] +} +ui_cancel={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194305,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":88,"key_label":0,"unicode":120,"echo":false,"script":null) +] +} interact={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) @@ -37,6 +60,14 @@ adv_text={ ] } +[internationalization] + +locale/translations_pot_files=PackedStringArray("res://src/dialogue/main.dialogue") + +[layer_names] + +2d_physics/layer_1="actionables" + [rendering] textures/canvas_textures/default_texture_filter=0 diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd new file mode 100644 index 0000000..624ffcf --- /dev/null +++ b/src/autoloads/player_state.gd @@ -0,0 +1,21 @@ +extends Node + +# these are functions that can be called in the dialog system + +func has_boots(): + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + return player.has_boots + +func give_boots(): + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + player.give_boots() + var ui = current_scene.get_node("UI") + ui.bootIcon.visible = true + + + +# ion know what this returns +func _get_current_scene(): + return get_tree().get_root().get_children()[2] diff --git a/src/dialogue/main.dialogue b/src/dialogue/main.dialogue new file mode 100644 index 0000000..4fbb0b7 --- /dev/null +++ b/src/dialogue/main.dialogue @@ -0,0 +1,11 @@ +~ start + +if PlayerState.has_boots() == false + The chest contained boots. + do PlayerState.give_boots() + They fit you perfectly. (did you see the change in the ui!?!?) + An air of unease overwhelms you. + Something is wrong... +else: + You already took the boots. Nothing has been added in between then and now. +=> END \ No newline at end of file diff --git a/src/dialogue/main.dialogue.import b/src/dialogue/main.dialogue.import new file mode 100644 index 0000000..48041f3 --- /dev/null +++ b/src/dialogue/main.dialogue.import @@ -0,0 +1,15 @@ +[remap] + +importer="dialogue_manager_compiler_11" +type="Resource" +uid="uid://dlw5a1hy61hj8" +path="res://.godot/imported/main.dialogue-149136ebb6b3f65449302c7d610ce455.tres" + +[deps] + +source_file="res://src/dialogue/main.dialogue" +dest_files=["res://.godot/imported/main.dialogue-149136ebb6b3f65449302c7d610ce455.tres"] + +[params] + +defaults=true diff --git a/src/main/main.gd b/src/main/main.gd index eabe0e6..38ff892 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -12,6 +12,7 @@ var map_room_id_dict: Dictionary = { #Not perfect but works for time constraint 2: preload('res://src/maps/map-2.tscn'), 3: preload('res://src/maps/map-3.tscn') } + var shuffled_maps:Array = [] var current_map_id diff --git a/src/maps/map-1.tscn b/src/maps/map-1.tscn index 52d3adf..7459311 100644 --- a/src/maps/map-1.tscn +++ b/src/maps/map-1.tscn @@ -1,8 +1,10 @@ -[gd_scene load_steps=4 format=3 uid="uid://deqm4to4ptnq0"] +[gd_scene load_steps=6 format=3 uid="uid://deqm4to4ptnq0"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_vosps"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_web8r"] [ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_8x2ye"] +[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="4_hq2kf"] +[ext_resource type="Resource" uid="uid://dlw5a1hy61hj8" path="res://src/dialogue/main.dialogue" id="5_gjl3f"] [node name="Map" type="Node2D"] script = ExtResource("1_web8r") @@ -11,7 +13,7 @@ script = ExtResource("1_web8r") tile_set = ExtResource("1_vosps") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 196615, 3, 262144) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -20,3 +22,7 @@ position = Vector2(80, 48) [node name="stairs" parent="." instance=ExtResource("3_8x2ye")] position = Vector2(160, 96) toward_room_id = 2 + +[node name="Chest" parent="." instance=ExtResource("4_hq2kf")] +position = Vector2(112, 64) +dialog_resource = ExtResource("5_gjl3f") diff --git a/src/maps/map-4.tscn b/src/maps/map-4.tscn new file mode 100644 index 0000000..55e1f6a --- /dev/null +++ b/src/maps/map-4.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=3 format=3 uid="uid://22clf0thbdqv"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_qwjcs"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_1bcx7"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_qwjcs") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_1bcx7") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 196615, 3, 262144, 393226, 3, 196608) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 48) diff --git a/src/player/player.gd b/src/player/player.gd index 6929468..c744812 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -33,16 +33,13 @@ func get_input_vector(event: InputEvent) -> Vector2: return dir -func _input(event: InputEvent) -> void: - # don't do anything if you aren't allowed to - if !is_actionable: - return +func _unhandled_input(event: InputEvent) -> void: var _input_dir := get_input_vector(event) #check what group the next tile is in based on your raycast if _input_dir != Vector2.ZERO: _move(_input_dir) return - if event.is_action_pressed('interact'): + if event.is_action_pressed('ui_accept'): _interact() @@ -72,3 +69,7 @@ func _interact() -> void: if interact_tile.is_in_group('interact'): interact_tile._on_interaction(self) +func give_boots(): + var boots = boots_packed_scene.instantiate() + add_child(boots) + has_boots = true \ No newline at end of file diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 643a03b..207ee78 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -1,11 +1,15 @@ extends Area2D signal inspected + +@export var dialog_resource: DialogueResource +@export var dialog_start: String = "start" + var opened:bool = false @onready var sprite = $Sprite2D #bad solution but not a bad solution YET -@onready var ui:UI = get_parent().get_parent().get_parent().get_node('UI') +@onready var ui:UI = get_parent().get_parent().get_node('UI') func _init() -> void: add_to_group('interact') @@ -15,24 +19,30 @@ func _ready() -> void: pass func _on_interaction(player:Player) -> void: - if !opened: - opened = true - - # we should make a generic chest with the ability to give any item (although we'd need to have some sort of item data strucutre) - if !player.has_boots: - print('boots') - var boots = player.boots_packed_scene.instantiate() - player.add_child(boots) - player.has_boots = true - - ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) - $Sprite2D.frame = 1 - - # added a cheeky placeholder if statement for when the player is already wearing boots and opens a new chest - # did it for shits and giggles - elif player.has_boots: - print('boots again?') - - ui.render_text(['The chest contained the same boots.', "The ones you're already wearing.", 'You don\'t need them right now.']) + if dialog_resource == null: + # we need 404.dialog lol + return + + DialogueManager.show_example_dialogue_balloon(load("res://src/dialogue/main.dialogue"),"start") + $Sprite2D.frame = 1 + + #if !opened: + #opened = true + + ## we should make a generic chest with the ability to give any item (although we'd need to have some sort of item data strucutre) + #if !player.has_boots: + #print('boots') + #var boots = player.boots_packed_scene.instantiate() + #player.add_child(boots) + #player.has_boots = true + + #ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) + + ## added a cheeky placeholder if statement for when the player is already wearing boots and opens a new chest + ## did it for shits and giggles + #elif player.has_boots: + #print('boots again?') + + #ui.render_text(['The chest contained the same boots.', "The ones you're already wearing.", 'You don\'t need them right now.']) diff --git a/src/scene-tiles/chest/chest.tscn b/src/scene-tiles/chest/chest.tscn index 9d1385c..97d3972 100644 --- a/src/scene-tiles/chest/chest.tscn +++ b/src/scene-tiles/chest/chest.tscn @@ -10,10 +10,12 @@ size = Vector2(16, 16) script = ExtResource("1_j2k5u") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(8, 8) shape = SubResource("RectangleShape2D_vdfc5") [node name="Sprite2D" type="Sprite2D" parent="."] texture = ExtResource("1_dpxiw") +centered = false hframes = 2 region_enabled = true region_rect = Rect2(128, 96, 32, 16) From 11dadfb7853c5ec0e116149561e5b7b5567d503c Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Thu, 11 Apr 2024 11:10:27 -0400 Subject: [PATCH 21/86] what is happening --- src/autoloads/player_state.gd | 19 +++++-------------- src/dialogue/main.dialogue | 3 ++- src/scene-tiles/chest/chest.gd | 23 ++++------------------- 3 files changed, 11 insertions(+), 34 deletions(-) diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd index 624ffcf..b432bc0 100644 --- a/src/autoloads/player_state.gd +++ b/src/autoloads/player_state.gd @@ -1,21 +1,12 @@ extends Node -# these are functions that can be called in the dialog system +#can you use an onready in a autoload? when is an autoload put in the scene??? func has_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - return player.has_boots - -func give_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - player.give_boots() - var ui = current_scene.get_node("UI") - ui.bootIcon.visible = true - - + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + return player.has_boots # ion know what this returns func _get_current_scene(): - return get_tree().get_root().get_children()[2] + return get_tree().get_root().get_children()[0] diff --git a/src/dialogue/main.dialogue b/src/dialogue/main.dialogue index 4fbb0b7..6968a02 100644 --- a/src/dialogue/main.dialogue +++ b/src/dialogue/main.dialogue @@ -1,8 +1,9 @@ ~ start if PlayerState.has_boots() == false + change from vscode The chest contained boots. - do PlayerState.give_boots() + do PlayerState._give_boots() They fit you perfectly. (did you see the change in the ui!?!?) An air of unease overwhelms you. Something is wrong... diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 207ee78..4cb98a8 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -23,26 +23,11 @@ func _on_interaction(player:Player) -> void: # we need 404.dialog lol return + if opened: + return + + opened = true DialogueManager.show_example_dialogue_balloon(load("res://src/dialogue/main.dialogue"),"start") $Sprite2D.frame = 1 - #if !opened: - #opened = true - - ## we should make a generic chest with the ability to give any item (although we'd need to have some sort of item data strucutre) - #if !player.has_boots: - #print('boots') - #var boots = player.boots_packed_scene.instantiate() - #player.add_child(boots) - #player.has_boots = true - - #ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) - - ## added a cheeky placeholder if statement for when the player is already wearing boots and opens a new chest - ## did it for shits and giggles - #elif player.has_boots: - #print('boots again?') - - #ui.render_text(['The chest contained the same boots.', "The ones you're already wearing.", 'You don\'t need them right now.']) - From c8b77139b9221f580072a79d33885a100eb471ed Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Thu, 11 Apr 2024 11:19:31 -0400 Subject: [PATCH 22/86] thing should behave? --- project.godot | 2 +- src/autoloads/player_state.gd | 19 ++++++++++++++----- src/dialogue/main.dialogue | 1 - 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/project.godot b/project.godot index 5f834c1..0c34852 100644 --- a/project.godot +++ b/project.godot @@ -18,7 +18,7 @@ config/icon="res://icon.svg" [autoload] DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd" -PlayerState="*res://src/autoloads/player_state.gd" +PlayerState="res://src/autoloads/player_state.gd" [display] diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd index b432bc0..ed93a91 100644 --- a/src/autoloads/player_state.gd +++ b/src/autoloads/player_state.gd @@ -1,12 +1,21 @@ extends Node -#can you use an onready in a autoload? when is an autoload put in the scene??? +# these are functions that can be called in the dialog system func has_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - return player.has_boots + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + return player.has_boots + +func _give_boots(): + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + player.give_boots() + var ui = current_scene.get_node("UI") + ui.bootIcon.visible = true + + # ion know what this returns func _get_current_scene(): - return get_tree().get_root().get_children()[0] + return get_tree().get_root().get_children()[2] \ No newline at end of file diff --git a/src/dialogue/main.dialogue b/src/dialogue/main.dialogue index 6968a02..e735370 100644 --- a/src/dialogue/main.dialogue +++ b/src/dialogue/main.dialogue @@ -1,7 +1,6 @@ ~ start if PlayerState.has_boots() == false - change from vscode The chest contained boots. do PlayerState._give_boots() They fit you perfectly. (did you see the change in the ui!?!?) From f18f2dfc7db1f01b6a20c7e2cce0ac3ce671d4b6 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Thu, 11 Apr 2024 12:16:09 -0400 Subject: [PATCH 23/86] addon makes it brokey --- .gitignore | 2 + addons/dialogue_manager/DialogueManager.cs | 394 ---- addons/dialogue_manager/LICENSE | 21 - addons/dialogue_manager/assets/icon.svg | 52 - .../dialogue_manager/assets/icon.svg.import | 38 - .../assets/responses_menu.svg | 52 - .../assets/responses_menu.svg.import | 38 - addons/dialogue_manager/assets/update.svg | 71 - .../dialogue_manager/assets/update.svg.import | 37 - .../dialogue_manager/components/code_edit.gd | 425 ---- .../components/code_edit.tscn | 56 - .../code_edit_syntax_highlighter.gd | 382 ---- .../components/dialogue_cache.gd | 160 -- .../components/download_update_panel.gd | 84 - .../components/download_update_panel.tscn | 60 - .../components/errors_panel.gd | 85 - .../components/errors_panel.tscn | 56 - .../dialogue_manager/components/files_list.gd | 144 -- .../components/files_list.tscn | 40 - .../components/find_in_files.gd | 229 --- .../components/find_in_files.tscn | 139 -- .../components/parse_result.gd | 10 - addons/dialogue_manager/components/parser.gd | 1780 ----------------- .../components/resolved_line_data.gd | 15 - .../components/resolved_tag_data.gd | 10 - .../components/search_and_replace.gd | 210 -- .../components/search_and_replace.tscn | 87 - .../dialogue_manager/components/title_list.gd | 67 - .../components/title_list.tscn | 45 - .../components/update_button.gd | 126 -- .../components/update_button.tscn | 42 - addons/dialogue_manager/constants.gd | 187 -- addons/dialogue_manager/dialogue_label.gd | 226 --- addons/dialogue_manager/dialogue_label.tscn | 19 - addons/dialogue_manager/dialogue_line.gd | 98 - addons/dialogue_manager/dialogue_manager.gd | 1235 ------------ .../dialogue_reponses_menu.gd | 131 -- addons/dialogue_manager/dialogue_resource.gd | 42 - addons/dialogue_manager/dialogue_response.gd | 62 - .../editor_translation_parser_plugin.gd | 43 - .../example_balloon/ExampleBalloon.cs | 204 -- .../example_balloon/example_balloon.gd | 141 -- .../example_balloon/example_balloon.tscn | 149 -- .../small_example_balloon.tscn | 173 -- addons/dialogue_manager/import_plugin.gd | 113 -- addons/dialogue_manager/l10n/en.mo | Bin 9770 -> 0 bytes addons/dialogue_manager/l10n/en.po | 481 ----- addons/dialogue_manager/l10n/es.po | 457 ----- addons/dialogue_manager/l10n/translations.pot | 471 ----- addons/dialogue_manager/l10n/zh.po | 408 ---- addons/dialogue_manager/l10n/zh_TW.po | 408 ---- addons/dialogue_manager/plugin.cfg | 7 - addons/dialogue_manager/plugin.gd | 276 --- addons/dialogue_manager/settings.gd | 184 -- addons/dialogue_manager/test_scene.gd | 31 - addons/dialogue_manager/test_scene.tscn | 7 - addons/dialogue_manager/utilities/builtins.gd | 468 ----- addons/dialogue_manager/views/main_view.gd | 1100 ---------- addons/dialogue_manager/views/main_view.tscn | 334 ---- .../dialogue_manager/views/settings_view.gd | 280 --- .../dialogue_manager/views/settings_view.tscn | 221 -- 61 files changed, 2 insertions(+), 12911 deletions(-) delete mode 100644 addons/dialogue_manager/DialogueManager.cs delete mode 100644 addons/dialogue_manager/LICENSE delete mode 100644 addons/dialogue_manager/assets/icon.svg delete mode 100644 addons/dialogue_manager/assets/icon.svg.import delete mode 100644 addons/dialogue_manager/assets/responses_menu.svg delete mode 100644 addons/dialogue_manager/assets/responses_menu.svg.import delete mode 100644 addons/dialogue_manager/assets/update.svg delete mode 100644 addons/dialogue_manager/assets/update.svg.import delete mode 100644 addons/dialogue_manager/components/code_edit.gd delete mode 100644 addons/dialogue_manager/components/code_edit.tscn delete mode 100644 addons/dialogue_manager/components/code_edit_syntax_highlighter.gd delete mode 100644 addons/dialogue_manager/components/dialogue_cache.gd delete mode 100644 addons/dialogue_manager/components/download_update_panel.gd delete mode 100644 addons/dialogue_manager/components/download_update_panel.tscn delete mode 100644 addons/dialogue_manager/components/errors_panel.gd delete mode 100644 addons/dialogue_manager/components/errors_panel.tscn delete mode 100644 addons/dialogue_manager/components/files_list.gd delete mode 100644 addons/dialogue_manager/components/files_list.tscn delete mode 100644 addons/dialogue_manager/components/find_in_files.gd delete mode 100644 addons/dialogue_manager/components/find_in_files.tscn delete mode 100644 addons/dialogue_manager/components/parse_result.gd delete mode 100644 addons/dialogue_manager/components/parser.gd delete mode 100644 addons/dialogue_manager/components/resolved_line_data.gd delete mode 100644 addons/dialogue_manager/components/resolved_tag_data.gd delete mode 100644 addons/dialogue_manager/components/search_and_replace.gd delete mode 100644 addons/dialogue_manager/components/search_and_replace.tscn delete mode 100644 addons/dialogue_manager/components/title_list.gd delete mode 100644 addons/dialogue_manager/components/title_list.tscn delete mode 100644 addons/dialogue_manager/components/update_button.gd delete mode 100644 addons/dialogue_manager/components/update_button.tscn delete mode 100644 addons/dialogue_manager/constants.gd delete mode 100644 addons/dialogue_manager/dialogue_label.gd delete mode 100644 addons/dialogue_manager/dialogue_label.tscn delete mode 100644 addons/dialogue_manager/dialogue_line.gd delete mode 100644 addons/dialogue_manager/dialogue_manager.gd delete mode 100644 addons/dialogue_manager/dialogue_reponses_menu.gd delete mode 100644 addons/dialogue_manager/dialogue_resource.gd delete mode 100644 addons/dialogue_manager/dialogue_response.gd delete mode 100644 addons/dialogue_manager/editor_translation_parser_plugin.gd delete mode 100644 addons/dialogue_manager/example_balloon/ExampleBalloon.cs delete mode 100644 addons/dialogue_manager/example_balloon/example_balloon.gd delete mode 100644 addons/dialogue_manager/example_balloon/example_balloon.tscn delete mode 100644 addons/dialogue_manager/example_balloon/small_example_balloon.tscn delete mode 100644 addons/dialogue_manager/import_plugin.gd delete mode 100644 addons/dialogue_manager/l10n/en.mo delete mode 100644 addons/dialogue_manager/l10n/en.po delete mode 100644 addons/dialogue_manager/l10n/es.po delete mode 100644 addons/dialogue_manager/l10n/translations.pot delete mode 100644 addons/dialogue_manager/l10n/zh.po delete mode 100644 addons/dialogue_manager/l10n/zh_TW.po delete mode 100644 addons/dialogue_manager/plugin.cfg delete mode 100644 addons/dialogue_manager/plugin.gd delete mode 100644 addons/dialogue_manager/settings.gd delete mode 100644 addons/dialogue_manager/test_scene.gd delete mode 100644 addons/dialogue_manager/test_scene.tscn delete mode 100644 addons/dialogue_manager/utilities/builtins.gd delete mode 100644 addons/dialogue_manager/views/main_view.gd delete mode 100644 addons/dialogue_manager/views/main_view.tscn delete mode 100644 addons/dialogue_manager/views/settings_view.gd delete mode 100644 addons/dialogue_manager/views/settings_view.tscn diff --git a/.gitignore b/.gitignore index 75eb8af..f0e8e76 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ # Godot 4+ specific ignores .godot/ .vscode/settings.json +# don't keep the addons in the repo +addons/ \ No newline at end of file diff --git a/addons/dialogue_manager/DialogueManager.cs b/addons/dialogue_manager/DialogueManager.cs deleted file mode 100644 index ae4f931..0000000 --- a/addons/dialogue_manager/DialogueManager.cs +++ /dev/null @@ -1,394 +0,0 @@ -using Godot; -using Godot.Collections; -using System; -using System.Reflection; -using System.Threading.Tasks; - -#nullable enable - -namespace DialogueManagerRuntime -{ - public enum TranslationSource - { - None, - Guess, - CSV, - PO - } - - public partial class DialogueManager : Node - { - public delegate void PassedTitleEventHandler(string title); - public delegate void GotDialogueEventHandler(DialogueLine dialogueLine); - public delegate void MutatedEventHandler(Dictionary mutation); - public delegate void DialogueEndedEventHandler(Resource dialogueResource); - - public static PassedTitleEventHandler? PassedTitle; - public static GotDialogueEventHandler? GotDialogue; - public static MutatedEventHandler? Mutated; - public static DialogueEndedEventHandler? DialogueEnded; - - [Signal] public delegate void ResolvedEventHandler(Variant value); - - private static GodotObject? instance; - public static GodotObject Instance - { - get - { - if (instance == null) - { - instance = Engine.GetSingleton("DialogueManager"); - } - return instance; - } - } - - - public static Godot.Collections.Array GameStates - { - get => (Godot.Collections.Array)Instance.Get("game_states"); - set => Instance.Set("game_states", value); - } - - - public static bool IncludeSingletons - { - get => (bool)Instance.Get("include_singletons"); - set => Instance.Set("include_singletons", value); - } - - - public static bool IncludeClasses - { - get => (bool)Instance.Get("include_classes"); - set => Instance.Set("include_classes", value); - } - - - public static TranslationSource TranslationSource - { - get => (TranslationSource)(int)Instance.Get("translation_source"); - set => Instance.Set("translation_source", (int)value); - } - - - public static Func<Node> GetCurrentScene - { - set => Instance.Set("get_current_scene", Callable.From(value)); - } - - - public void Prepare() - { - Instance.Connect("passed_title", Callable.From((string title) => PassedTitle?.Invoke(title))); - Instance.Connect("got_dialogue", Callable.From((RefCounted line) => GotDialogue?.Invoke(new DialogueLine(line)))); - Instance.Connect("mutated", Callable.From((Dictionary mutation) => Mutated?.Invoke(mutation))); - Instance.Connect("dialogue_ended", Callable.From((Resource dialogueResource) => DialogueEnded?.Invoke(dialogueResource))); - } - - - public static async Task<GodotObject> GetSingleton() - { - if (instance != null) return instance; - - var tree = Engine.GetMainLoop(); - int x = 0; - - // Try and find the singleton for a few seconds - while (!Engine.HasSingleton("DialogueManager") && x < 300) - { - await tree.ToSignal(tree, SceneTree.SignalName.ProcessFrame); - x++; - } - - // If it times out something is wrong - if (x >= 300) - { - throw new Exception("The DialogueManager singleton is missing."); - } - - instance = Engine.GetSingleton("DialogueManager"); - return instance; - } - - public static async Task<DialogueLine?> GetNextDialogueLine(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - Instance.Call("_bridge_get_next_dialogue_line", dialogueResource, key, extraGameStates ?? new Array<Variant>()); - var result = await Instance.ToSignal(Instance, "bridge_get_next_dialogue_line_completed"); - - if ((RefCounted)result[0] == null) return null; - - return new DialogueLine((RefCounted)result[0]); - } - - - public static CanvasLayer ShowExampleDialogueBalloon(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - return (CanvasLayer)Instance.Call("show_example_dialogue_balloon", dialogueResource, key, extraGameStates ?? new Array<Variant>()); - } - - - public static Node ShowDialogueBalloonScene(string balloonScene, Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array<Variant>()); - } - - public static Node ShowDialogueBalloonScene(PackedScene balloonScene, Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array<Variant>()); - } - - public static Node ShowDialogueBalloonScene(Node balloonScene, Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array<Variant>()); - } - - - public static Node ShowDialogueBalloon(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - return (Node)Instance.Call("show_dialogue_balloon", dialogueResource, key, extraGameStates ?? new Array<Variant>()); - } - - - public static async void Mutate(Dictionary mutation, Array<Variant>? extraGameStates = null, bool isInlineMutation = false) - { - Instance.Call("_bridge_mutate", mutation, extraGameStates ?? new Array<Variant>(), isInlineMutation); - await Instance.ToSignal(Instance, "bridge_mutated"); - } - - - public bool ThingHasMethod(GodotObject thing, string method) - { - MethodInfo? info = thing.GetType().GetMethod(method, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); - return info != null; - } - - - public async void ResolveThingMethod(GodotObject thing, string method, Array<Variant> args) - { - MethodInfo? info = thing.GetType().GetMethod(method, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); - - if (info == null) return; - -#nullable disable - // Convert the method args to something reflection can handle - ParameterInfo[] argTypes = info.GetParameters(); - object[] _args = new object[argTypes.Length]; - for (int i = 0; i < argTypes.Length; i++) - { - if (i < args.Count && args[i].Obj != null) - { - _args[i] = Convert.ChangeType(args[i].Obj, argTypes[i].ParameterType); - } - else if (argTypes[i].DefaultValue != null) - { - _args[i] = argTypes[i].DefaultValue; - } - } - - // Add a single frame wait in case the method returns before signals can listen - await ToSignal(Engine.GetMainLoop(), SceneTree.SignalName.ProcessFrame); - - if (info.ReturnType == typeof(Task)) - { - await (Task)info.Invoke(thing, _args); - EmitSignal(SignalName.Resolved, null); - } - else - { - var value = (Variant)info.Invoke(thing, _args); - EmitSignal(SignalName.Resolved, value); - } - } -#nullable enable - } - - - public partial class DialogueLine : RefCounted - { - private string type = "dialogue"; - public string Type - { - get => type; - set => type = value; - } - - private string next_id = ""; - public string NextId - { - get => next_id; - set => next_id = value; - } - - private string character = ""; - public string Character - { - get => character; - set => character = value; - } - - private string text = ""; - public string Text - { - get => text; - set => text = value; - } - - private string translation_key = ""; - public string TranslationKey - { - get => translation_key; - set => translation_key = value; - } - - private Array<DialogueResponse> responses = new Array<DialogueResponse>(); - public Array<DialogueResponse> Responses - { - get => responses; - } - - private string? time = null; - public string? Time - { - get => time; - } - - private Dictionary pauses = new Dictionary(); - public Dictionary Pauses - { - get => pauses; - } - - private Dictionary speeds = new Dictionary(); - public Dictionary Speeds - { - get => speeds; - } - - private Array<Godot.Collections.Array> inline_mutations = new Array<Godot.Collections.Array>(); - public Array<Godot.Collections.Array> InlineMutations - { - get => inline_mutations; - } - - private Array<Variant> extra_game_states = new Array<Variant>(); - - private Array<string> tags = new Array<string>(); - public Array<string> Tags - { - get => tags; - } - - public DialogueLine(RefCounted data) - { - type = (string)data.Get("type"); - next_id = (string)data.Get("next_id"); - character = (string)data.Get("character"); - text = (string)data.Get("text"); - translation_key = (string)data.Get("translation_key"); - pauses = (Dictionary)data.Get("pauses"); - speeds = (Dictionary)data.Get("speeds"); - inline_mutations = (Array<Godot.Collections.Array>)data.Get("inline_mutations"); - time = (string)data.Get("time"); - tags = (Array<string>)data.Get("tags"); - - foreach (var response in (Array<RefCounted>)data.Get("responses")) - { - responses.Add(new DialogueResponse(response)); - } - } - - - public string GetTagValue(string tagName) - { - string wrapped = $"{tagName}="; - foreach (var tag in tags) - { - if (tag.StartsWith(wrapped)) - { - return tag.Substring(wrapped.Length); - } - } - return ""; - } - - public override string ToString() - { - switch (type) - { - case "dialogue": - return $"<DialogueLine character=\"{character}\" text=\"{text}\">"; - case "mutation": - return "<DialogueLine mutation>"; - default: - return ""; - } - } - } - - - public partial class DialogueResponse : RefCounted - { - private string next_id = ""; - public string NextId - { - get => next_id; - set => next_id = value; - } - - private bool is_allowed = true; - public bool IsAllowed - { - get => is_allowed; - set => is_allowed = value; - } - - private string text = ""; - public string Text - { - get => text; - set => text = value; - } - - private string translation_key = ""; - public string TranslationKey - { - get => translation_key; - set => translation_key = value; - } - - private Array<string> tags = new Array<string>(); - public Array<string> Tags - { - get => tags; - } - - public DialogueResponse(RefCounted data) - { - next_id = (string)data.Get("next_id"); - is_allowed = (bool)data.Get("is_allowed"); - text = (string)data.Get("text"); - translation_key = (string)data.Get("translation_key"); - tags = (Array<string>)data.Get("tags"); - } - - public string GetTagValue(string tagName) - { - string wrapped = $"{tagName}="; - foreach (var tag in tags) - { - if (tag.StartsWith(wrapped)) - { - return tag.Substring(wrapped.Length); - } - } - return ""; - } - - public override string ToString() - { - return $"<DialogueResponse text=\"{text}\""; - } - } -} - diff --git a/addons/dialogue_manager/LICENSE b/addons/dialogue_manager/LICENSE deleted file mode 100644 index 4167139..0000000 --- a/addons/dialogue_manager/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -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. diff --git a/addons/dialogue_manager/assets/icon.svg b/addons/dialogue_manager/assets/icon.svg deleted file mode 100644 index e3b2d4f..0000000 --- a/addons/dialogue_manager/assets/icon.svg +++ /dev/null @@ -1,52 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - width="16" - height="16" - viewBox="0 0 4.2333333 4.2333335" - version="1.1" - id="svg291" - inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" - sodipodi:docname="icon.svg" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg"> - <sodipodi:namedview - id="namedview293" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageshadow="2" - inkscape:pageopacity="0.0" - inkscape:pagecheckerboard="0" - inkscape:document-units="px" - showgrid="false" - width="1920px" - units="px" - borderlayer="true" - inkscape:showpageshadow="false" - inkscape:zoom="18.583334" - inkscape:cx="9.3901342" - inkscape:cy="13.506726" - inkscape:window-width="1440" - inkscape:window-height="890" - inkscape:window-x="-6" - inkscape:window-y="-6" - inkscape:window-maximized="1" - inkscape:current-layer="layer1" - inkscape:deskcolor="#d1d1d1" /> - <defs - id="defs288" /> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1"> - <path - id="path3615" - style="clip-rule:evenodd;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.00206088;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:40" - d="M 2.3616237,0.32495581 C 2.2890187,0.32469635 2.2284054,0.32546079 2.1926162,0.32687081 1.8949218,0.33860011 1.5033325,0.34148331 1.2561323,0.35080961 1.1421362,0.35510961 0.51253678,0.28342811 0.31150932,0.54279835 0.0999174,0.81580911 0.23804642,2.0559707 0.22102032,2.2314376 0.21014342,2.34358 0.20066442,2.896122 0.41300909,3.1219592 0.60816171,3.3295105 0.90177008,3.3453424 0.95593994,3.3503348 1.0177384,3.3560148 1.5339832,3.3499581 1.574996,3.351287 c 0.015313,4.929e-4 0.064365,0.00139 0.1311843,0.00287 0.027454,0.1558591 0.1348816,0.4055146 0.2891801,0.5079801 0.1737371,0.1153709 0.5840376,0.1672049 0.633898,0.1417174 0.033884,-0.017324 0.2120976,-0.020746 0.2120976,-0.03926 -3e-7,-0.00281 -0.1359618,-0.075872 -0.1795407,-0.098149 C 2.5715112,3.8202919 2.5190005,3.7242168 2.4506759,3.6543568 2.4244915,3.6275965 2.4279949,3.4751553 2.4315249,3.3742737 2.5495776,3.3733989 2.8697241,3.3839918 2.9371113,3.3838502 3.0975326,3.3835266 3.5689747,3.3993771 3.8080031,3.1818075 4.0962844,2.9193889 4.0228795,2.3969451 4.0186641,2.3267119 4.013119,2.2343213 4.0250025,1.6246294 4.0162732,1.4864616 4.0028561,1.274529 4.0737709,0.94594107 3.8376871,0.59402732 3.6199123,0.26941205 3.0597025,0.34195584 3.0151516,0.33931907 2.9077682,0.33296522 2.5794394,0.32573415 2.3616237,0.32495581 Z m 0.9580286,0.52713126 a 0.19209624,0.19209624 0 0 1 0.063678,0.007659 A 0.19209624,0.19209624 0 0 1 3.5121209,1.10057 c -0.019132,0.064024 -0.02934,0.114542 -0.029205,0.1517718 a 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.786e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.786e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.786e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 c -0.00327,0.073938 -0.00815,0.1281478 -0.00336,0.1646986 a 0.19211544,0.19211544 0 0 1 0.00192,0.01963 c 0.00122,0.044001 0.00215,0.096625 -0.00383,0.1560806 a 0.19211544,0.19211544 0 0 1 -0.0091,0.04309 c 0.00152,-0.00444 0.00292,-0.00713 0.00383,-0.00814 0.00239,4.689e-4 -5.16e-5,0.023556 -0.012927,0.069423 l -4.786e-4,0.00144 c -0.00322,0.018276 -0.00512,0.060008 -0.010052,0.1072455 2.1e-6,-1.573e-4 -1.8e-5,0.00348 0,0.00383 8.03e-5,0.00155 -1.3e-6,0.00456 0,0.016278 A 0.19209624,0.19209624 0 0 1 3.256933,2.0270008 0.19209624,0.19209624 0 0 1 3.0649443,1.835012 c -2e-7,-8.421e-4 -2.139e-4,-0.00933 0,-0.025375 a 0.19211544,0.19211544 0 0 1 0.00192,-0.021545 c 0.00393,-0.029738 0.00172,-0.085222 0.018193,-0.1627834 a 0.19211544,0.19211544 0 0 1 0.00336,-0.014841 c -0.00488,0.016544 -0.00842,-0.00696 0.0091,-0.066071 0.00128,-0.023365 8.374e-4,-0.05167 0,-0.083786 5.837e-4,0.00531 0.0012,0.010844 0.00192,0.016278 l -0.00192,-0.020109 c -0.00868,-0.082861 -0.00275,-0.1509043 0,-0.2044368 -3.839e-4,-0.1048643 0.02617,-0.1913531 0.047392,-0.26236915 A 0.19209624,0.19209624 0 0 1 3.3196523,0.85208707 Z M 3.097501,1.5443956 c -3.745e-4,0.00682 -8.326e-4,0.013152 -0.00144,0.019151 l 0.00862,-0.043569 c -0.00298,0.00868 -0.00496,0.016879 -0.00718,0.024418 z M 1.7483131,1.0129554 a 0.19211544,0.19211544 0 0 1 0.1804981,0.1292692 c 0.081754,0.230866 0.1671804,0.4503689 0.2566234,0.6094805 0.060542,-0.039278 0.13119,-0.081733 0.2374723,-0.083307 0.030189,-0.00505 0.059326,-0.01228 0.095756,-0.00527 0.053638,0.010328 0.1089723,0.045047 0.1426749,0.086658 0.067401,0.08322 0.064433,0.1543836 0.063678,0.2082669 -0.00151,0.1077673 -0.021788,0.2137733 -0.022023,0.2044369 A 0.19209624,0.19209624 0 0 1 2.5167468,2.3578344 0.19209624,0.19209624 0 0 1 2.3194915,2.1715908 c -7.704e-4,-0.030281 0.0031,-0.035159 0.00527,-0.059847 -0.035038,0.025653 -0.068601,0.053251 -0.1139486,0.081391 A 0.19211544,0.19211544 0 0 1 1.9704693,2.1624936 c -0.016009,-0.016679 -0.012719,-0.040218 -0.027291,-0.057933 -0.0053,0.038768 -0.013896,0.105592 -0.030642,0.1881586 -0.00975,0.048046 -0.018553,0.093357 -0.036386,0.1412386 -0.00891,0.023941 -0.00752,0.046058 -0.061283,0.09767 -0.00671,0.00645 -0.015395,0.013123 -0.025375,0.020109 -0.00997,0.00699 -0.03579,0.021291 -0.036386,0.021545 -0.00119,5.072e-4 -0.1089417,0.013114 -0.1101182,0.012927 -5.885e-4,-9.26e-5 -0.052085,-0.016004 -0.052666,-0.016278 -5.848e-4,-2.741e-4 -0.028877,-0.016619 -0.039745,-0.025375 -0.021733,-0.017517 -0.036349,-0.03491 -0.045484,-0.048835 a 0.19211544,0.19211544 0 0 1 -0.00718,-0.012927 C 1.405201,2.3135107 1.3718331,2.1230884 1.3226821,1.9293306 1.296257,1.9926645 1.2702556,2.0360279 1.236503,2.1127015 c -0.00662,0.020181 -0.015708,0.041777 -0.033514,0.067986 -0.021835,0.03214 -0.067722,0.078719 -0.1393236,0.090488 -0.0716015,0.011769 -0.13415192,-0.018894 -0.16469865,-0.043568 -0.0305472,-0.024673 -0.042975,-0.046717 -0.0541012,-0.065113 -0.0389429,-0.064387 -0.0578673,-0.09647 -0.0526653,-0.176189 0.002344,0.010422 0.004713,0.021014 0.00718,0.031599 L 0.79602584,1.94896 c -0.001684,0.013201 -0.003086,0.025254 -0.003828,0.036387 C 0.74313508,1.766609 0.72147035,1.582656 0.68734765,1.3720365 A 0.19209624,0.19209624 0 0 1 0.84486459,1.1527576 0.19209624,0.19209624 0 0 1 1.0655799,1.3102746 c 0.012592,0.077723 0.025291,0.1404024 0.035908,0.2097036 0.010745,-0.014664 0.00973,-0.026756 0.021545,-0.041175 -0.0011,-0.00222 0.032336,-0.054265 0.079956,-0.1067668 0.013605,-0.015001 0.028067,-0.03269 0.061762,-0.052665 0.033694,-0.019975 0.1078148,-0.047748 0.1843284,-0.018193 0.068698,0.026536 0.092715,0.077474 0.1086819,0.1139485 -0.00167,-0.078755 -0.00808,-0.1467436 -0.00383,-0.2207153 A 0.19211544,0.19211544 0 0 1 1.7186306,1.0153489 0.19211544,0.19211544 0 0 1 1.748314,1.0129564 Z M 1.2365027,2.1127015 c 0.0015,-0.00457 0.00304,-0.00894 0.00431,-0.013405 l -0.00862,0.02346 c 0.00152,-0.00352 0.00282,-0.00667 0.00431,-0.010052 z M 3.1899043,2.2683033 A 0.19374282,0.20281166 0 0 1 3.3833296,2.4713039 0.19374282,0.20281166 0 0 1 3.1899043,2.6743046 0.19374282,0.20281166 0 0 1 2.9960006,2.4713039 0.19374282,0.20281166 0 0 1 3.1899043,2.2683033 Z" - fill="#E0E0E0" /> - </g> -</svg> diff --git a/addons/dialogue_manager/assets/icon.svg.import b/addons/dialogue_manager/assets/icon.svg.import deleted file mode 100644 index 3b6fd5e..0000000 --- a/addons/dialogue_manager/assets/icon.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://d3lr2uas6ax8v" -path="res://.godot/imported/icon.svg-17eb5d3e2a3cfbe59852220758c5b7bd.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/dialogue_manager/assets/icon.svg" -dest_files=["res://.godot/imported/icon.svg-17eb5d3e2a3cfbe59852220758c5b7bd.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=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/dialogue_manager/assets/responses_menu.svg b/addons/dialogue_manager/assets/responses_menu.svg deleted file mode 100644 index 4e4089d..0000000 --- a/addons/dialogue_manager/assets/responses_menu.svg +++ /dev/null @@ -1,52 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - width="16" - height="16" - viewBox="0 0 4.2333333 4.2333335" - version="1.1" - id="svg291" - inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" - sodipodi:docname="responses_menu.svg" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg"> - <sodipodi:namedview - id="namedview293" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageshadow="2" - inkscape:pageopacity="0.0" - inkscape:pagecheckerboard="0" - inkscape:document-units="px" - showgrid="false" - width="1920px" - units="px" - borderlayer="true" - inkscape:showpageshadow="false" - inkscape:deskcolor="#d1d1d1" - inkscape:zoom="45.254834" - inkscape:cx="7.8334173" - inkscape:cy="6.5959804" - inkscape:window-width="2560" - inkscape:window-height="1377" - inkscape:window-x="-8" - inkscape:window-y="-8" - inkscape:window-maximized="1" - inkscape:current-layer="layer1" /> - <defs - id="defs288" /> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1"> - <path - id="rect181" - style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:1.77487;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill" - d="M 1.5875 0.26458334 L 1.5875 0.79375001 L 4.2333334 0.79375001 L 4.2333334 0.26458334 L 1.5875 0.26458334 z M 0 0.83147381 L 0 2.4189738 L 1.3229167 1.6252238 L 0 0.83147381 z M 1.5875 1.3229167 L 1.5875 1.8520834 L 4.2333334 1.8520834 L 4.2333334 1.3229167 L 1.5875 1.3229167 z M 1.5875 2.38125 L 1.5875 2.9104167 L 4.2333334 2.9104167 L 4.2333334 2.38125 L 1.5875 2.38125 z M 1.5875 3.4395834 L 1.5875 3.9687501 L 4.2333334 3.9687501 L 4.2333334 3.4395834 L 1.5875 3.4395834 z " - fill="#E0E0E0" /> - </g> -</svg> diff --git a/addons/dialogue_manager/assets/responses_menu.svg.import b/addons/dialogue_manager/assets/responses_menu.svg.import deleted file mode 100644 index 83355fc..0000000 --- a/addons/dialogue_manager/assets/responses_menu.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://drjfciwitjm83" -path="res://.godot/imported/responses_menu.svg-87cf63ca685d53616205049572f4eb8f.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/dialogue_manager/assets/responses_menu.svg" -dest_files=["res://.godot/imported/responses_menu.svg-87cf63ca685d53616205049572f4eb8f.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=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/dialogue_manager/assets/update.svg b/addons/dialogue_manager/assets/update.svg deleted file mode 100644 index a5b80ee..0000000 --- a/addons/dialogue_manager/assets/update.svg +++ /dev/null @@ -1,71 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - width="300" - height="80" - viewBox="0 0 79.374999 21.166667" - version="1.1" - id="svg291" - inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" - sodipodi:docname="update.svg" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg"> - <sodipodi:namedview - id="namedview293" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageshadow="2" - inkscape:pageopacity="0.0" - inkscape:pagecheckerboard="0" - inkscape:document-units="px" - showgrid="false" - width="1920px" - units="px" - borderlayer="true" - inkscape:showpageshadow="false" - inkscape:zoom="1" - inkscape:cx="180.5" - inkscape:cy="111" - inkscape:window-width="1440" - inkscape:window-height="890" - inkscape:window-x="-6" - inkscape:window-y="-6" - inkscape:window-maximized="1" - inkscape:current-layer="layer1" - inkscape:deskcolor="#d1d1d1" /> - <defs - id="defs288" /> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1"> - <rect - style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1" - id="rect2462" - width="13.228261" - height="9.4236727" - x="32.95359" - y="4.2143135" - ry="0.90020913" /> - <path - id="path3615" - style="clip-rule:evenodd;fill:#bd93f9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.52916667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:40;stroke-opacity:1;stroke-dasharray:none" - d="m 40.714378,3.0283624 c -0.297691,-0.00106 -0.546217,0.00208 -0.692956,0.00785 -1.220595,0.048091 -2.826171,0.059913 -3.83973,0.098152 -0.467403,0.017637 -3.048858,-0.2762743 -3.873101,0.7871837 -0.867561,1.1193864 -0.301209,6.2042409 -0.371018,6.9236829 -0.04459,0.459801 -0.08346,2.725309 0.787183,3.651277 0.800155,0.850991 2.003996,0.915905 2.2261,0.936375 0.253383,0.02331 2.370068,-0.0015 2.538226,0.0039 0.0628,0.002 0.263908,0.0057 0.537877,0.01177 0.112572,0.639046 0.553034,1.662672 1.185683,2.082798 0.712348,0.473037 2.394644,0.685566 2.599079,0.581063 0.138939,-0.07104 0.869634,-0.08507 0.869634,-0.160971 -2e-6,-0.01157 -0.557466,-0.311089 -0.736145,-0.402428 -0.370261,-0.189241 -0.585564,-0.583165 -0.865705,-0.869601 -0.107353,-0.109727 -0.09299,-0.734754 -0.07851,-1.148384 0.484034,-0.0035 1.796685,0.03983 2.072983,0.03926 0.657753,-0.0013 2.590738,0.06366 3.570791,-0.828408 1.181999,-1.075941 0.881027,-3.218042 0.863743,-3.50601 -0.02274,-0.378815 0.02599,-2.878646 -0.0098,-3.4451551 C 47.443688,6.9217592 47.734446,5.5744981 46.766467,4.1315973 45.873555,2.8006244 43.57661,3.0980651 43.393944,3.087254 42.953654,3.0612024 41.607455,3.0315527 40.714378,3.0283624 Z m 3.928065,2.1613198 a 0.78762433,0.78762433 0 0 1 0.261087,0.031405 0.78762433,0.78762433 0 0 1 0.528062,0.9874148 c -0.07845,0.2625075 -0.120302,0.46964 -0.119753,0.6222881 a 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 c -0.01334,0.3031554 -0.03341,0.5254256 -0.01373,0.6752895 a 0.78770308,0.78770308 0 0 1 0.0078,0.080487 c 0.0051,0.1804113 0.0088,0.3961799 -0.0157,0.6399549 a 0.78770308,0.78770308 0 0 1 -0.03726,0.1767104 c 0.0063,-0.018206 0.01197,-0.029244 0.0157,-0.033361 0.0098,0.00192 -2.12e-4,0.096583 -0.05301,0.2846419 l -0.002,0.00589 c -0.01314,0.074935 -0.02097,0.2460417 -0.04122,0.4397235 9e-6,-6.455e-4 -7.3e-5,0.014282 0,0.015695 3.29e-4,0.00634 -4e-6,0.018697 0,0.066743 A 0.78762433,0.78762433 0 0 1 44.385285,10.007011 0.78762433,0.78762433 0 0 1 43.598102,9.2198268 c -2e-6,-0.00345 -8.77e-4,-0.038262 0,-0.1040456 a 0.78770308,0.78770308 0 0 1 0.0078,-0.088337 c 0.01609,-0.12193 0.0071,-0.3494247 0.07459,-0.6674374 a 0.78770308,0.78770308 0 0 1 0.01373,-0.060853 c -0.02001,0.067835 -0.03455,-0.028543 0.03731,-0.270902 0.0053,-0.0958 0.0035,-0.2118566 0,-0.3435347 0.0024,0.021788 0.0049,0.044462 0.0078,0.066743 l -0.0078,-0.082447 c -0.03559,-0.3397458 -0.01118,-0.6187306 0,-0.8382225 -0.0016,-0.4299563 0.107334,-0.784574 0.194343,-1.0757507 A 0.78762433,0.78762433 0 0 1 44.642342,5.189683 Z m -0.910856,2.8385724 c -0.0015,0.027966 -0.0033,0.053926 -0.0059,0.078522 l 0.03533,-0.1786397 c -0.01216,0.035586 -0.02031,0.069207 -0.02945,0.100118 z M 38.199709,5.8492675 a 0.78770308,0.78770308 0 0 1 0.740071,0.5300233 c 0.335202,0.9465866 0.685464,1.8465826 1.052196,2.4989649 0.248233,-0.1610476 0.537898,-0.3351164 0.973672,-0.3415703 0.123774,-0.020676 0.243246,-0.050347 0.392613,-0.021583 0.219925,0.042345 0.446803,0.1847018 0.584989,0.3553102 0.276354,0.3412161 0.264185,0.6329968 0.261087,0.8539269 -0.0061,0.4418625 -0.08934,0.8765035 -0.09031,0.8382235 a 0.78762433,0.78762433 0 0 1 -0.763625,0.800915 0.78762433,0.78762433 0 0 1 -0.808777,-0.763625 c -0.0031,-0.124158 0.01275,-0.144159 0.02158,-0.245384 -0.143662,0.105178 -0.281267,0.218336 -0.467201,0.333717 a 0.78770308,0.78770308 0 0 1 -0.985442,-0.125632 c -0.06564,-0.06838 -0.05215,-0.164899 -0.111905,-0.237533 -0.0217,0.158952 -0.05697,0.432943 -0.125637,0.771479 -0.03994,0.196996 -0.07606,0.382777 -0.1492,0.579101 -0.03653,0.09815 -0.03084,0.18885 -0.251272,0.400462 -0.02751,0.02645 -0.06313,0.05381 -0.104038,0.08246 -0.04091,0.02866 -0.146748,0.0873 -0.1492,0.08834 -0.0049,0.0022 -0.446678,0.05377 -0.451502,0.05301 -0.0024,-3.79e-4 -0.213555,-0.06562 -0.215939,-0.06674 -0.0024,-0.0011 -0.118379,-0.06813 -0.162933,-0.104037 -0.08911,-0.07182 -0.149043,-0.143138 -0.186495,-0.20023 a 0.78770308,0.78770308 0 0 1 -0.02945,-0.05301 c -0.380095,-0.694111 -0.516908,-1.474871 -0.718435,-2.269308 -0.108354,0.2596787 -0.214957,0.437476 -0.353349,0.751849 -0.02715,0.08274 -0.06441,0.171293 -0.13741,0.278753 -0.08952,0.131779 -0.277668,0.322761 -0.571248,0.371015 -0.293578,0.04826 -0.550045,-0.07747 -0.67529,-0.178628 C 34.592013,10.728363 34.541064,10.63798 34.495437,10.562564 34.33576,10.298568 34.25817,10.167022 34.2795,9.8401611 c 0.0096,0.042731 0.01942,0.086159 0.02945,0.1295617 L 34.29521,9.6870414 c -0.0069,0.054124 -0.01275,0.1035434 -0.0157,0.1491901 C 34.07835,8.9393633 33.98952,8.1851278 33.849612,7.3215552 a 0.78762433,0.78762433 0 0 1 0.645844,-0.8990776 0.78762433,0.78762433 0 0 1 0.904966,0.645844 c 0.05164,0.3186785 0.103704,0.5756714 0.147218,0.859817 0.04404,-0.060125 0.03987,-0.1097017 0.08834,-0.1688245 -0.0045,-0.0091 0.132583,-0.2224951 0.327832,-0.4377603 0.05578,-0.061504 0.115083,-0.1340347 0.253236,-0.2159342 0.138154,-0.081904 0.442057,-0.1957766 0.755775,-0.074598 0.281673,0.1088032 0.380145,0.3176572 0.445613,0.4672063 -0.0069,-0.3229043 -0.03312,-0.6016714 -0.0157,-0.9049667 a 0.78770308,0.78770308 0 0 1 0.675286,-0.7341808 0.78770308,0.78770308 0 0 1 0.121714,-0.00981 z m -2.098502,4.5091295 c 0.0061,-0.01874 0.01255,-0.03666 0.01766,-0.05496 l -0.03533,0.09619 c 0.0063,-0.01442 0.01158,-0.02735 0.01766,-0.04123 z m 8.00925,0.63799 a 0.79437562,0.83155922 0 0 1 0.793073,0.832334 0.79437562,0.83155922 0 0 1 -0.793073,0.832335 0.79437562,0.83155922 0 0 1 -0.795036,-0.832335 0.79437562,0.83155922 0 0 1 0.795036,-0.832334 z" /> - <path - id="path2353" - style="clip-rule:evenodd;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#4d425c;stroke-width:0.529167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:40;stroke-dasharray:none;stroke-opacity:1" - d="m 40.538948,3.0282389 c -0.29769,-0.00106 -0.546242,0.00198 -0.692981,0.00775 -1.220593,0.048091 -2.826517,0.059946 -3.840075,0.098185 -0.467403,0.017637 -3.048907,-0.2759081 -3.873149,0.7875489 -0.86756,1.1193852 -0.300711,6.2041675 -0.37052,6.9236085 -0.04459,0.4598 -0.08361,2.724973 0.787032,3.65094 0.800154,0.85099 2.004117,0.915907 2.226221,0.936377 0.253382,0.02331 2.369672,-0.0013 2.537829,0.0041 0.0628,0.002 0.263983,0.0058 0.537952,0.01189 0.112572,0.639046 0.553326,1.662435 1.185974,2.082561 0.712347,0.473036 2.394373,0.685862 2.598808,0.58136 0.138939,-0.07104 0.869714,-0.08533 0.869714,-0.161231 -2e-6,-0.01157 -0.55771,-0.31122 -0.736389,-0.402559 -0.370261,-0.189241 -0.585439,-0.582762 -0.86558,-0.869198 -0.107353,-0.109727 -0.09303,-0.735137 -0.07855,-1.148767 0.484033,-0.0035 1.79696,0.03984 2.073258,0.03927 0.657752,-0.0013 2.59079,0.06369 3.570842,-0.828373 1.181997,-1.07594 0.880797,-3.217762 0.863513,-3.505729 -0.02274,-0.378815 0.02597,-2.8787595 -0.0098,-3.4452681 C 47.268006,6.9217821 47.558753,5.5744301 46.590775,4.1315308 45.697864,2.8005592 43.401037,3.0979612 43.218371,3.0871501 42.778082,3.0610985 41.432024,3.0314292 40.538948,3.0282389 Z" /> - <path - id="rect1625" - style="fill:#50fa7b;fill-opacity:1;stroke:#0f451d;stroke-width:0.593381;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" - d="m 50.52517,5.3570989 c -0.643062,0 -1.160653,0.5900216 -1.160653,1.3229166 v 1.0764201 h -1.07642 c -0.732895,0 -1.322916,0.5175908 -1.322916,1.1606533 0,0.643061 0.590021,1.1611691 1.322916,1.1611691 h 1.07642 v 1.076421 c 0,0.732895 0.517591,1.322917 1.160653,1.322917 0.643062,0 1.160653,-0.590022 1.160653,-1.322917 v -1.076421 h 1.076937 c 0.732895,0 1.322916,-0.5181081 1.322916,-1.1611691 0,-0.6430625 -0.590021,-1.1606533 -1.322916,-1.1606533 H 51.685823 V 6.6800155 c 0,-0.732895 -0.517591,-1.3229166 -1.160653,-1.3229166 z" /> - <path - id="path2678" - style="fill:#50fa7b;fill-opacity:1;stroke:#0f451d;stroke-width:0.593381;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" - d="m 57.791691,5.357099 c -0.643062,0 -1.160653,0.5900216 -1.160653,1.3229166 v 1.0764201 h -1.07642 c -0.732895,0 -1.322916,0.5175908 -1.322916,1.1606522 0,0.643062 0.590021,1.1611701 1.322916,1.1611701 h 1.07642 v 1.076421 c 0,0.732895 0.517591,1.322917 1.160653,1.322917 0.643062,0 1.160653,-0.590022 1.160653,-1.322917 v -1.076421 h 1.076937 c 0.732895,0 1.322916,-0.5181081 1.322916,-1.1611701 0,-0.6430614 -0.590021,-1.1606522 -1.322916,-1.1606522 H 58.952344 V 6.6800156 c 0,-0.732895 -0.517591,-1.3229166 -1.160653,-1.3229166 z" /> - </g> -</svg> diff --git a/addons/dialogue_manager/assets/update.svg.import b/addons/dialogue_manager/assets/update.svg.import deleted file mode 100644 index 2d8171a..0000000 --- a/addons/dialogue_manager/assets/update.svg.import +++ /dev/null @@ -1,37 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://d3baj6rygkb3f" -path="res://.godot/imported/update.svg-f1628866ed4eb2e13e3b81f75443687e.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://addons/dialogue_manager/assets/update.svg" -dest_files=["res://.godot/imported/update.svg-f1628866ed4eb2e13e3b81f75443687e.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 diff --git a/addons/dialogue_manager/components/code_edit.gd b/addons/dialogue_manager/components/code_edit.gd deleted file mode 100644 index e57c1af..0000000 --- a/addons/dialogue_manager/components/code_edit.gd +++ /dev/null @@ -1,425 +0,0 @@ -@tool -extends CodeEdit - - -signal active_title_change(title: String) -signal error_clicked(line_number: int) -signal external_file_requested(path: String, title: String) - - -const DialogueSyntaxHighlighter = preload("./code_edit_syntax_highlighter.gd") - - -# A link back to the owner MainView -var main_view - -# Theme overrides for syntax highlighting, etc -var theme_overrides: Dictionary: - set(value): - theme_overrides = value - - syntax_highlighter = DialogueSyntaxHighlighter.new() - - # General UI - add_theme_color_override("font_color", theme_overrides.text_color) - add_theme_color_override("background_color", theme_overrides.background_color) - add_theme_color_override("current_line_color", theme_overrides.current_line_color) - add_theme_font_override("font", get_theme_font("source", "EditorFonts")) - add_theme_font_size_override("font_size", theme_overrides.font_size * theme_overrides.scale) - font_size = round(theme_overrides.font_size) - get: - return theme_overrides - -# Any parse errors -var errors: Array: - set(next_errors): - errors = next_errors - for i in range(0, get_line_count()): - var is_error: bool = false - for error in errors: - if error.line_number == i: - is_error = true - mark_line_as_error(i, is_error) - _on_code_edit_caret_changed() - get: - return errors - -# The last selection (if there was one) so we can remember it for refocusing -var last_selected_text: String - -var font_size: int: - set(value): - font_size = value - add_theme_font_size_override("font_size", font_size * theme_overrides.scale) - get: - return font_size - -var WEIGHTED_RANDOM_PREFIX: RegEx = RegEx.create_from_string("^\\%[\\d.]+\\s") - - -func _ready() -> void: - # Add error gutter - add_gutter(0) - set_gutter_type(0, TextEdit.GUTTER_TYPE_ICON) - - # Add comment delimiter - if not has_comment_delimiter("#"): - add_comment_delimiter("#", "", true) - - syntax_highlighter = DialogueSyntaxHighlighter.new() - - -func _gui_input(event: InputEvent) -> void: - if event is InputEventKey and event.is_pressed(): - match event.as_text(): - "Ctrl+Equal", "Command+Equal": - self.font_size += 1 - get_viewport().set_input_as_handled() - "Ctrl+Minus", "Command+Minus": - self.font_size -= 1 - get_viewport().set_input_as_handled() - "Ctrl+0", "Command+0": - self.font_size = theme_overrides.font_size - get_viewport().set_input_as_handled() - "Ctrl+K", "Command+K": - toggle_comment() - get_viewport().set_input_as_handled() - "Alt+Up": - move_line(-1) - get_viewport().set_input_as_handled() - "Alt+Down": - move_line(1) - get_viewport().set_input_as_handled() - - elif event is InputEventMouse: - match event.as_text(): - "Ctrl+Mouse Wheel Up", "Command+Mouse Wheel Up": - self.font_size += 1 - get_viewport().set_input_as_handled() - "Ctrl+Mouse Wheel Down", "Command+Mouse Wheel Down": - self.font_size -= 1 - get_viewport().set_input_as_handled() - - -func _can_drop_data(at_position: Vector2, data) -> bool: - if typeof(data) != TYPE_DICTIONARY: return false - if data.type != "files": return false - - var files: PackedStringArray = Array(data.files).filter(func(f): return f.get_extension() == "dialogue") - return files.size() > 0 - - -func _drop_data(at_position: Vector2, data) -> void: - var replace_regex: RegEx = RegEx.create_from_string("[^a-zA-Z_0-9]+") - - var files: PackedStringArray = Array(data.files).filter(func(f): return f.get_extension() == "dialogue") - for file in files: - # Don't import the file into itself - if file == main_view.current_file_path: continue - - var path = file.replace("res://", "").replace(".dialogue", "") - # Find the first non-import line in the file to add our import - var lines = text.split("\n") - for i in range(0, lines.size()): - if not lines[i].begins_with("import "): - insert_line_at(i, "import \"%s\" as %s\n" % [file, replace_regex.sub(path, "_", true)]) - set_caret_line(i) - break - - -func _request_code_completion(force: bool) -> void: - var cursor: Vector2 = get_cursor() - var current_line: String = get_line(cursor.y) - - if ("=> " in current_line or "=>< " in current_line) and (cursor.x > current_line.find("=>")): - var prompt: String = current_line.split("=>")[1] - if prompt.begins_with("< "): - prompt = prompt.substr(2) - else: - prompt = prompt.substr(1) - - if "=> " in current_line: - if matches_prompt(prompt, "end"): - add_code_completion_option(CodeEdit.KIND_CLASS, "END", "END".substr(prompt.length()), theme_overrides.text_color, get_theme_icon("Stop", "EditorIcons")) - if matches_prompt(prompt, "end!"): - add_code_completion_option(CodeEdit.KIND_CLASS, "END!", "END!".substr(prompt.length()), theme_overrides.text_color, get_theme_icon("Stop", "EditorIcons")) - - # Get all titles, including those in imports - var parser: DialogueManagerParser = DialogueManagerParser.new() - parser.prepare(text, main_view.current_file_path, false) - for title in parser.titles: - if "/" in title: - var bits = title.split("/") - if matches_prompt(prompt, bits[0]) or matches_prompt(prompt, bits[1]): - add_code_completion_option(CodeEdit.KIND_CLASS, title, title.substr(prompt.length()), theme_overrides.text_color, get_theme_icon("CombineLines", "EditorIcons")) - elif matches_prompt(prompt, title): - add_code_completion_option(CodeEdit.KIND_CLASS, title, title.substr(prompt.length()), theme_overrides.text_color, get_theme_icon("ArrowRight", "EditorIcons")) - update_code_completion_options(true) - parser.free() - return - - var name_so_far: String = WEIGHTED_RANDOM_PREFIX.sub(current_line.strip_edges(), "") - if name_so_far != "" and name_so_far[0].to_upper() == name_so_far[0]: - # Only show names starting with that character - var names: PackedStringArray = get_character_names(name_so_far) - if names.size() > 0: - for name in names: - add_code_completion_option(CodeEdit.KIND_CLASS, name + ": ", name.substr(name_so_far.length()) + ": ", theme_overrides.text_color, get_theme_icon("Sprite2D", "EditorIcons")) - update_code_completion_options(true) - else: - cancel_code_completion() - - -func _filter_code_completion_candidates(candidates: Array) -> Array: - # Not sure why but if this method isn't overridden then all completions are wrapped in quotes. - return candidates - - -func _confirm_code_completion(replace: bool) -> void: - var completion = get_code_completion_option(get_code_completion_selected_index()) - begin_complex_operation() - # Delete any part of the text that we've already typed - for i in range(0, completion.display_text.length() - completion.insert_text.length()): - backspace() - # Insert the whole match - insert_text_at_caret(completion.display_text) - end_complex_operation() - - # Close the autocomplete menu on the next tick - call_deferred("cancel_code_completion") - - -### Helpers - - -# Get the current caret as a Vector2 -func get_cursor() -> Vector2: - return Vector2(get_caret_column(), get_caret_line()) - - -# Set the caret from a Vector2 -func set_cursor(from_cursor: Vector2) -> void: - set_caret_line(from_cursor.y) - set_caret_column(from_cursor.x) - - -# Check if a prompt is the start of a string without actually being that string -func matches_prompt(prompt: String, matcher: String) -> bool: - return prompt.length() < matcher.length() and matcher.to_lower().begins_with(prompt.to_lower()) - - -## Get a list of titles from the current text -func get_titles() -> PackedStringArray: - var titles = PackedStringArray([]) - var lines = text.split("\n") - for line in lines: - if line.begins_with("~ "): - titles.append(line.substr(2).strip_edges()) - return titles - - -## Work out what the next title above the current line is -func check_active_title() -> void: - var line_number = get_caret_line() - var lines = text.split("\n") - # Look at each line above this one to find the next title line - for i in range(line_number, -1, -1): - if lines[i].begins_with("~ "): - active_title_change.emit(lines[i].replace("~ ", "")) - return - - active_title_change.emit("") - - -# Move the caret line to match a given title -func go_to_title(title: String) -> void: - var lines = text.split("\n") - for i in range(0, lines.size()): - if lines[i].strip_edges() == "~ " + title: - set_caret_line(i) - center_viewport_to_caret() - - -func get_character_names(beginning_with: String) -> PackedStringArray: - var names: PackedStringArray = [] - var lines = text.split("\n") - for line in lines: - if ": " in line: - var name: String = WEIGHTED_RANDOM_PREFIX.sub(line.split(": ")[0].strip_edges(), "") - if not name in names and matches_prompt(beginning_with, name): - names.append(name) - return names - - -# Mark a line as an error or not -func mark_line_as_error(line_number: int, is_error: bool) -> void: - if is_error: - set_line_background_color(line_number, theme_overrides.error_line_color) - set_line_gutter_icon(line_number, 0, get_theme_icon("StatusError", "EditorIcons")) - else: - set_line_background_color(line_number, theme_overrides.background_color) - set_line_gutter_icon(line_number, 0, null) - - -# Insert or wrap some bbcode at the caret/selection -func insert_bbcode(open_tag: String, close_tag: String = "") -> void: - if close_tag == "": - insert_text_at_caret(open_tag) - grab_focus() - else: - var selected_text = get_selected_text() - insert_text_at_caret("%s%s%s" % [open_tag, selected_text, close_tag]) - grab_focus() - set_caret_column(get_caret_column() - close_tag.length()) - -# Insert text at current caret position -# Move Caret down 1 line if not => END -func insert_text(text: String) -> void: - if text != "=> END": - insert_text_at_caret(text+"\n") - set_caret_line(get_caret_line()+1) - else: - insert_text_at_caret(text) - grab_focus() - - -# Toggle the selected lines as comments -func toggle_comment() -> void: - begin_complex_operation() - - var comment_delimiter: String = delimiter_comments[0] - var is_first_line: bool = true - var will_comment: bool = true - var selections: Array = [] - var line_offsets: Dictionary = {} - - for caret_index in range(0, get_caret_count()): - var from_line: int = get_caret_line(caret_index) - var from_column: int = get_caret_column(caret_index) - var to_line: int = get_caret_line(caret_index) - var to_column: int = get_caret_column(caret_index) - - if has_selection(caret_index): - from_line = get_selection_from_line(caret_index) - to_line = get_selection_to_line(caret_index) - from_column = get_selection_from_column(caret_index) - to_column = get_selection_to_column(caret_index) - - selections.append({ - from_line = from_line, - from_column = from_column, - to_line = to_line, - to_column = to_column - }) - - for line_number in range(from_line, to_line + 1): - if line_offsets.has(line_number): continue - - var line_text: String = get_line(line_number) - - # The first line determines if we are commenting or uncommentingg - if is_first_line: - is_first_line = false - will_comment = not line_text.strip_edges().begins_with(comment_delimiter) - - # Only comment/uncomment if the current line needs to - if will_comment: - set_line(line_number, comment_delimiter + line_text) - line_offsets[line_number] = 1 - elif line_text.begins_with(comment_delimiter): - set_line(line_number, line_text.substr(comment_delimiter.length())) - line_offsets[line_number] = -1 - else: - line_offsets[line_number] = 0 - - for caret_index in range(0, get_caret_count()): - var selection: Dictionary = selections[caret_index] - select( - selection.from_line, - selection.from_column + line_offsets[selection.from_line], - selection.to_line, - selection.to_column + line_offsets[selection.to_line], - caret_index - ) - set_caret_column(selection.from_column + line_offsets[selection.from_line], false, caret_index) - - end_complex_operation() - - text_set.emit() - text_changed.emit() - - -# Move the selected lines up or down -func move_line(offset: int) -> void: - offset = clamp(offset, -1, 1) - - var cursor = get_cursor() - var reselect: bool = false - var from: int = cursor.y - var to: int = cursor.y - if has_selection(): - reselect = true - from = get_selection_from_line() - to = get_selection_to_line() - - var lines := text.split("\n") - - # We can't move the lines out of bounds - if from + offset < 0 or to + offset >= lines.size(): return - - var target_from_index = from - 1 if offset == -1 else to + 1 - var target_to_index = to if offset == -1 else from - var line_to_move = lines[target_from_index] - lines.remove_at(target_from_index) - lines.insert(target_to_index, line_to_move) - - text = "\n".join(lines) - - cursor.y += offset - from += offset - to += offset - if reselect: - select(from, 0, to, get_line_width(to)) - set_cursor(cursor) - text_changed.emit() - - -### Signals - - -func _on_code_edit_symbol_validate(symbol: String) -> void: - if symbol.begins_with("res://") and symbol.ends_with(".dialogue"): - set_symbol_lookup_word_as_valid(true) - return - - for title in get_titles(): - if symbol == title: - set_symbol_lookup_word_as_valid(true) - return - set_symbol_lookup_word_as_valid(false) - - -func _on_code_edit_symbol_lookup(symbol: String, line: int, column: int) -> void: - if symbol.begins_with("res://") and symbol.ends_with(".dialogue"): - external_file_requested.emit(symbol, "") - else: - go_to_title(symbol) - - -func _on_code_edit_text_changed() -> void: - request_code_completion(true) - - -func _on_code_edit_text_set() -> void: - queue_redraw() - - -func _on_code_edit_caret_changed() -> void: - check_active_title() - last_selected_text = get_selected_text() - - -func _on_code_edit_gutter_clicked(line: int, gutter: int) -> void: - var line_errors = errors.filter(func(error): return error.line_number == line) - if line_errors.size() > 0: - error_clicked.emit(line) diff --git a/addons/dialogue_manager/components/code_edit.tscn b/addons/dialogue_manager/components/code_edit.tscn deleted file mode 100644 index a974ea3..0000000 --- a/addons/dialogue_manager/components/code_edit.tscn +++ /dev/null @@ -1,56 +0,0 @@ -[gd_scene load_steps=4 format=3 uid="uid://civ6shmka5e8u"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit_syntax_highlighter.gd" id="1_58cfo"] -[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit.gd" id="1_g324i"] - -[sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_cobxx"] -script = ExtResource("1_58cfo") - -[node name="CodeEdit" type="CodeEdit"] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -text = "~ title_thing - -if this = \"that\" or 'this' -Nathan: Something -- Then [if test.thing() == 2.0] => somewhere -- Other => END! - -~ somewhere - -set has_something = true -=> END" -highlight_all_occurrences = true -highlight_current_line = true -draw_tabs = true -syntax_highlighter = SubResource("SyntaxHighlighter_cobxx") -scroll_past_end_of_file = true -minimap_draw = true -symbol_lookup_on_click = true -line_folding = true -gutters_draw_line_numbers = true -gutters_draw_fold_gutter = true -delimiter_strings = Array[String](["\" \""]) -delimiter_comments = Array[String](["#"]) -code_completion_enabled = true -code_completion_prefixes = Array[String]([">", "<"]) -indent_automatic = true -auto_brace_completion_enabled = true -auto_brace_completion_highlight_matching = true -auto_brace_completion_pairs = { -"\"": "\"", -"(": ")", -"[": "]", -"{": "}" -} -script = ExtResource("1_g324i") - -[connection signal="caret_changed" from="." to="." method="_on_code_edit_caret_changed"] -[connection signal="gutter_clicked" from="." to="." method="_on_code_edit_gutter_clicked"] -[connection signal="symbol_lookup" from="." to="." method="_on_code_edit_symbol_lookup"] -[connection signal="symbol_validate" from="." to="." method="_on_code_edit_symbol_validate"] -[connection signal="text_changed" from="." to="." method="_on_code_edit_text_changed"] -[connection signal="text_set" from="." to="." method="_on_code_edit_text_set"] diff --git a/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd b/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd deleted file mode 100644 index fe1b8bd..0000000 --- a/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd +++ /dev/null @@ -1,382 +0,0 @@ -@tool -extends SyntaxHighlighter - - -enum ExpressionType {DO, SET, IF} - - -var dialogue_manager_parser: DialogueManagerParser = DialogueManagerParser.new() - -var regex_titles: RegEx = RegEx.create_from_string("^\\s*(?<title>~\\s+[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+)") -var regex_comments: RegEx = RegEx.create_from_string("(?:(?>\"(?:\\\\\"|[^\"\\n])*\")[^\"\\n]*?\\s*(?<comment>#[^\\n]*)$|^[^\"#\\n]*?\\s*(?<comment2>#[^\\n]*))") -var regex_mutation: RegEx = RegEx.create_from_string("^\\s*(do|do!|set) (?<mutation>.*)") -var regex_condition: RegEx = RegEx.create_from_string("^\\s*(if|elif|while|else if) (?<condition>.*)") -var regex_wcondition: RegEx = RegEx.create_from_string("\\[if (?<condition>((?:[^\\[\\]]*)|(?:\\[(?1)\\]))*?)\\]") -var regex_wendif: RegEx = RegEx.create_from_string("\\[(\\/if|else)\\]") -var regex_rgroup: RegEx = RegEx.create_from_string("\\[\\[(?<options>.*?)\\]\\]") -var regex_endconditions: RegEx = RegEx.create_from_string("^\\s*(endif|else):?\\s*$") -var regex_tags: RegEx = RegEx.create_from_string("\\[(?<tag>(?!(?:ID:.*)|if)[a-zA-Z_][a-zA-Z0-9_]*!?)(?:[= ](?<val>[^\\[\\]]+))?\\](?:(?<text>(?!\\[\\/\\k<tag>\\]).*?)?(?<end>\\[\\/\\k<tag>\\]))?") -var regex_dialogue: RegEx = RegEx.create_from_string("^\\s*(?:(?<random>\\%[\\d.]* )|(?<response>- ))?(?:(?<character>[^#:]*): )?(?<dialogue>.*)$") -var regex_goto: RegEx = RegEx.create_from_string("=><? (?:(?<file>[^\\/]+)\\/)?(?<title>[^\\/]*)") -var regex_string: RegEx = RegEx.create_from_string("^(?<delimiter>[\"'])(?<content>(?:\\\\{2})*|(?:.*?[^\\\\](?:\\\\{2})*))\\1$") -var regex_escape: RegEx = RegEx.create_from_string("\\\\.") -var regex_number: RegEx = RegEx.create_from_string("^-?(?:(?:0x(?:[0-9A-Fa-f]{2})+)|(?:0b[01]+)|(?:\\d+(?:(?:[\\.]\\d*)?(?:e\\d+)?)|(?:_\\d+)+)?)$") -var regex_array: RegEx = RegEx.create_from_string("\\[((?>[^\\[\\]]+|(?R))*)\\]") -var regex_dict: RegEx = RegEx.create_from_string("^\\{((?>[^\\{\\}]+|(?R))*)\\}$") -var regex_kvdict: RegEx = RegEx.create_from_string("^\\s*(?<left>.*?)\\s*(?<colon>:|=)\\s*(?<right>[^\\/]+)$") -var regex_commas: RegEx = RegEx.create_from_string("([^,]+)(?:\\s*,\\s*)?") -var regex_assignment: RegEx = RegEx.create_from_string("^\\s*(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*(?<op>(?:\\/|\\*|-|\\+)?=)\\s*(?<val>.*)$") -var regex_varname: RegEx = RegEx.create_from_string("^\\s*(?!true|false|and|or|not|in|null)(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*$") -var regex_keyword: RegEx = RegEx.create_from_string("^\\s*(true|false|null)\\s*$") -var regex_function: RegEx = RegEx.create_from_string("^\\s*([a-zA-Z_][a-zA-Z_0-9]*\\s*)\\(") -var regex_comparison: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s*(?<op>==|>=|<=|<|>|!=)\\s*(?<right>.*)$") -var regex_blogical: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s+(?<op>and|or|in)\\s+(?<right>.*)$") -var regex_ulogical: RegEx = RegEx.create_from_string("^\\s*(?<op>not)\\s+(?<right>.*)$") -var regex_paren: RegEx = RegEx.create_from_string("\\((?<paren>((?:[^\\(\\)]*)|(?:\\((?1)\\)))*?)\\)") - -var cache: Dictionary = {} - - -func _notification(what: int) -> void: - if what == NOTIFICATION_PREDELETE: - dialogue_manager_parser.free() - - -func _clear_highlighting_cache() -> void: - cache = {} - - -## Returns the syntax coloring for a dialogue file line -func _get_line_syntax_highlighting(line: int) -> Dictionary: - var colors: Dictionary = {} - var text_edit: TextEdit = get_text_edit() - var text: String = text_edit.get_line(line) - - # Prevents an error from popping up while developing - if not is_instance_valid(text_edit) or text_edit.theme_overrides.is_empty(): - return colors - - # Disable this, as well as the line at the bottom of this function to remove the cache. - if text in cache: - return cache[text] - - # Comments, we have to remove them at this point so the rest of the processing is easier - # Counts both end-of-line and single-line comments - # Comments are not allowed within dialogue lines or response lines, so we ask the parser what it thinks the current line is - if not (dialogue_manager_parser.is_dialogue_line(text) or dialogue_manager_parser.is_response_line(text)) or dialogue_manager_parser.is_line_empty(text) or dialogue_manager_parser.is_import_line(text): - var comment_matches: Array[RegExMatch] = regex_comments.search_all(text) - for comment_match in comment_matches: - for i in ["comment", "comment2"]: - if i in comment_match.names: - colors[comment_match.get_start(i)] = {"color": text_edit.theme_overrides.comments_color} - text = text.substr(0, comment_match.get_start(i)) - - # Dialogues. - var dialogue_matches: Array[RegExMatch] = regex_dialogue.search_all(text) - for dialogue_match in dialogue_matches: - if "random" in dialogue_match.names: - colors[dialogue_match.get_start("random")] = {"color": text_edit.theme_overrides.symbols_color} - colors[dialogue_match.get_end("random")] = {"color": text_edit.theme_overrides.text_color} - if "response" in dialogue_match.names: - colors[dialogue_match.get_start("response")] = {"color": text_edit.theme_overrides.symbols_color} - colors[dialogue_match.get_end("response")] = {"color": text_edit.theme_overrides.text_color} - if "character" in dialogue_match.names: - colors[dialogue_match.get_start("character")] = {"color": text_edit.theme_overrides.members_color} - colors[dialogue_match.get_end("character")] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_dialogue_syntax_highlighting(dialogue_match.get_start("dialogue"), dialogue_match.get_string("dialogue")), true) - - # Title lines. - if dialogue_manager_parser.is_title_line(text): - var title_matches: Array[RegExMatch] = regex_titles.search_all(text) - for title_match in title_matches: - colors[title_match.get_start("title")] = {"color": text_edit.theme_overrides.titles_color} - - # Import lines. - var import_matches: Array[RegExMatch] = dialogue_manager_parser.IMPORT_REGEX.search_all(text) - for import_match in import_matches: - colors[import_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} - colors[import_match.get_start("path") - 1] = {"color": text_edit.theme_overrides.strings_color} - colors[import_match.get_end("path") + 1] = {"color": text_edit.theme_overrides.conditions_color} - colors[import_match.get_start("prefix")] = {"color": text_edit.theme_overrides.members_color} - colors[import_match.get_end("prefix")] = {"color": text_edit.theme_overrides.conditions_color} - - # Using clauses - var using_matches: Array[RegExMatch] = dialogue_manager_parser.USING_REGEX.search_all(text) - for using_match in using_matches: - colors[using_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} - colors[using_match.get_start("state") - 1] = {"color": text_edit.theme_overrides.text_color} - - # Condition keywords and expressions. - var condition_matches: Array[RegExMatch] = regex_condition.search_all(text) - for condition_match in condition_matches: - colors[condition_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} - colors[condition_match.get_end(1)] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_expression_syntax_highlighting(condition_match.get_start("condition"), ExpressionType.IF, condition_match.get_string("condition")), true) - # endif/else - var endcondition_matches: Array[RegExMatch] = regex_endconditions.search_all(text) - for endcondition_match in endcondition_matches: - colors[endcondition_match.get_start(1)] = {"color": text_edit.theme_overrides.conditions_color} - colors[endcondition_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - - # Mutations. - var mutation_matches: Array[RegExMatch] = regex_mutation.search_all(text) - for mutation_match in mutation_matches: - colors[mutation_match.get_start(0)] = {"color": text_edit.theme_overrides.mutations_color} - colors.merge(_get_expression_syntax_highlighting(mutation_match.get_start("mutation"), ExpressionType.DO if mutation_match.strings[1] == "do" else ExpressionType.SET, mutation_match.get_string("mutation")), true) - - # CodeEdit seems to have issues if the Dictionary keys weren't added in order? - var new_colors: Dictionary = {} - var ordered_keys: Array = colors.keys() - ordered_keys.sort() - for index in ordered_keys: - new_colors[index] = colors[index] - - cache[text] = new_colors - return new_colors - - -## Returns the syntax highlighting for a dialogue line -func _get_dialogue_syntax_highlighting(start_index: int, text: String) -> Dictionary: - var text_edit: TextEdit = get_text_edit() - var colors: Dictionary = {} - - # #tag style tags - var hashtag_matches: Array[RegExMatch] = dialogue_manager_parser.TAGS_REGEX.search_all(text) - for hashtag_match in hashtag_matches: - colors[start_index + hashtag_match.get_start(0)] = { "color": text_edit.theme_overrides.comments_color } - colors[start_index + hashtag_match.get_end(0)] = { "color": text_edit.theme_overrides.text_color } - - # Global tags, like bbcode. - var tag_matches: Array[RegExMatch] = regex_tags.search_all(text) - for tag_match in tag_matches: - colors[start_index + tag_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - if "val" in tag_match.names: - colors.merge(_get_literal_syntax_highlighting(start_index + tag_match.get_start("val"), tag_match.get_string("val")), true) - colors[start_index + tag_match.get_end("val")] = {"color": text_edit.theme_overrides.symbols_color} - # Showing the text color straight in the editor for better ease-of-use - if tag_match.get_string("tag") == "color": - colors[start_index + tag_match.get_start("val")] = {"color": Color.from_string(tag_match.get_string("val"), text_edit.theme_overrides.text_color)} - if "text" in tag_match.names: - colors[start_index + tag_match.get_start("text")] = {"color": text_edit.theme_overrides.text_color} - # Text can still contain tags if several effects are applied ([center][b]Something[/b][/center], so recursing - colors.merge(_get_dialogue_syntax_highlighting(start_index + tag_match.get_start("text"), tag_match.get_string("text")), true) - colors[start_index + tag_match.get_end("text")] = {"color": text_edit.theme_overrides.symbols_color} - if "end" in tag_match.names: - colors[start_index + tag_match.get_start("end")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + tag_match.get_end("end")] = {"color": text_edit.theme_overrides.text_color} - colors[start_index + tag_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - # ID tag. - var translation_matches: Array[RegExMatch] = dialogue_manager_parser.TRANSLATION_REGEX.search_all(text) - for translation_match in translation_matches: - colors[start_index + translation_match.get_start(0)] = {"color": text_edit.theme_overrides.comments_color} - colors[start_index + translation_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - # Replacements. - var replacement_matches: Array[RegExMatch] = dialogue_manager_parser.REPLACEMENTS_REGEX.search_all(text) - for replacement_match in replacement_matches: - colors[start_index + replacement_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + replacement_match.get_start(1)] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + replacement_match.get_start(1), replacement_match.strings[1]), true) - colors[start_index + replacement_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + replacement_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - # Jump at the end of a response. - var goto_matches: Array[RegExMatch] = regex_goto.search_all(text) - for goto_match in goto_matches: - colors[start_index + goto_match.get_start(0)] = {"color": text_edit.theme_overrides.jumps_color} - if "file" in goto_match.names: - colors[start_index + goto_match.get_start("file")] = {"color": text_edit.theme_overrides.members_color} - colors[start_index + goto_match.get_end("file")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + goto_match.get_start("title")] = {"color": text_edit.theme_overrides.titles_color} - colors[start_index + goto_match.get_end("title")] = {"color": text_edit.theme_overrides.jumps_color} - colors[start_index + goto_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - # Wrapped condition. - var wcondition_matches: Array[RegExMatch] = regex_wcondition.search_all(text) - for wcondition_match in wcondition_matches: - colors[start_index + wcondition_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + wcondition_match.get_start(0) + 1] = {"color": text_edit.theme_overrides.conditions_color} - colors[start_index + wcondition_match.get_start(0) + 3] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + wcondition_match.get_start("condition"), wcondition_match.get_string("condition")), true) - colors[start_index + wcondition_match.get_end("condition")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + wcondition_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - # [/if] tag for color matching with the opening tag - var wendif_matches: Array[RegExMatch] = regex_wendif.search_all(text) - for wendif_match in wendif_matches: - colors[start_index + wendif_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + wendif_match.get_start(1)] = {"color": text_edit.theme_overrides.conditions_color} - colors[start_index + wendif_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + wendif_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - # Random groups - var rgroup_matches: Array[RegExMatch] = regex_rgroup.search_all(text) - for rgroup_match in rgroup_matches: - colors[start_index + rgroup_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + rgroup_match.get_start("options")] = {"color": text_edit.theme_overrides.text_color} - var separator_matches: Array[RegExMatch] = RegEx.create_from_string("\\|").search_all(rgroup_match.get_string("options")) - for separator_match in separator_matches: - colors[start_index + rgroup_match.get_start("options") + separator_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + rgroup_match.get_start("options") + separator_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - colors[start_index + rgroup_match.get_end("options")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + rgroup_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - return colors - - -## Returns the syntax highlighting for an expression (mutation set/do, or condition) -func _get_expression_syntax_highlighting(start_index: int, type: ExpressionType, text: String) -> Dictionary: - var text_edit: TextEdit = get_text_edit() - var colors: Dictionary = {} - - if type == ExpressionType.SET: - var assignment_matches: Array[RegExMatch] = regex_assignment.search_all(text) - for assignment_match in assignment_matches: - colors[start_index + assignment_match.get_start("var")] = {"color": text_edit.theme_overrides.text_color} - if "attr" in assignment_match.names: - colors[start_index + assignment_match.get_start("attr")] = {"color": text_edit.theme_overrides.members_color} - colors[start_index + assignment_match.get_end("attr")] = {"color": text_edit.theme_overrides.text_color} - if "key" in assignment_match.names: - # Braces are outside of the key, so coloring them symbols_color - colors[start_index + assignment_match.get_start("key") - 1] = {"color": text_edit.theme_overrides.symbols_color} - colors.merge(_get_literal_syntax_highlighting(start_index + assignment_match.get_start("key"), assignment_match.get_string("key")), true) - colors[start_index + assignment_match.get_end("key")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + assignment_match.get_end("key") + 1] = {"color": text_edit.theme_overrides.text_color} - - colors[start_index + assignment_match.get_start("op")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + assignment_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + assignment_match.get_start("val"), assignment_match.get_string("val")), true) - else: - colors.merge(_get_literal_syntax_highlighting(start_index, text), true) - - return colors - - -## Returns the syntax highlighting for a literal. -## For this purpose, "literal" refers to a regular code line that could be used to get a value out of: -## - function calls -## - real literals (bool, string, int, float, etc.) -## - logical operators (>, <, >=, or, and, not, etc.) -func _get_literal_syntax_highlighting(start_index: int, text: String) -> Dictionary: - var text_edit: TextEdit = get_text_edit() - var colors: Dictionary = {} - - # Removing spaces at start/end of the literal - var text_length: int = text.length() - text = text.lstrip(" ") - start_index += text_length - text.length() - text = text.rstrip(" ") - - # Parenthesis expression. - var paren_matches: Array[RegExMatch] = regex_paren.search_all(text) - for paren_match in paren_matches: - colors[start_index + paren_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + paren_match.get_start(0) + 1] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + paren_match.get_start("paren"), paren_match.get_string("paren")), true) - colors[start_index + paren_match.get_end(0) - 1] = {"color": text_edit.theme_overrides.symbols_color} - - # Strings. - var string_matches: Array[RegExMatch] = regex_string.search_all(text) - for string_match in string_matches: - colors[start_index + string_match.get_start(0)] = {"color": text_edit.theme_overrides.strings_color} - if "content" in string_match.names: - var escape_matches: Array[RegExMatch] = regex_escape.search_all(string_match.get_string("content")) - for escape_match in escape_matches: - colors[start_index + string_match.get_start("content") + escape_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + string_match.get_start("content") + escape_match.get_end(0)] = {"color": text_edit.theme_overrides.strings_color} - - # Numbers. - var number_matches: Array[RegExMatch] = regex_number.search_all(text) - for number_match in number_matches: - colors[start_index + number_match.get_start(0)] = {"color": text_edit.theme_overrides.numbers_color} - - # Arrays. - var array_matches: Array[RegExMatch] = regex_array.search_all(text) - for array_match in array_matches: - colors[start_index + array_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors.merge(_get_list_syntax_highlighting(start_index + array_match.get_start(1), array_match.strings[1]), true) - colors[start_index + array_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - - # Dictionaries. - var dict_matches: Array[RegExMatch] = regex_dict.search_all(text) - for dict_match in dict_matches: - colors[start_index + dict_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors.merge(_get_list_syntax_highlighting(start_index + dict_match.get_start(1), dict_match.strings[1]), true) - colors[start_index + dict_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - - # Dictionary key: value pairs - var kvdict_matches: Array[RegExMatch] = regex_kvdict.search_all(text) - for kvdict_match in kvdict_matches: - colors.merge(_get_literal_syntax_highlighting(start_index + kvdict_match.get_start("left"), kvdict_match.get_string("left")), true) - colors[start_index + kvdict_match.get_start("colon")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + kvdict_match.get_end("colon")] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + kvdict_match.get_start("right"), kvdict_match.get_string("right")), true) - - # Booleans. - var bool_matches: Array[RegExMatch] = regex_keyword.search_all(text) - for bool_match in bool_matches: - colors[start_index + bool_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} - - # Functions. - var function_matches: Array[RegExMatch] = regex_function.search_all(text) - for function_match in function_matches: - var last_brace_index: int = text.rfind(")") - colors[start_index + function_match.get_start(1)] = {"color": text_edit.theme_overrides.mutations_color} - colors[start_index + function_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - colors.merge(_get_list_syntax_highlighting(start_index + function_match.get_end(0), text.substr(function_match.get_end(0), last_brace_index - function_match.get_end(0))), true) - colors[start_index + last_brace_index] = {"color": text_edit.theme_overrides.symbols_color} - - # Variables. - var varname_matches: Array[RegExMatch] = regex_varname.search_all(text) - for varname_match in varname_matches: - colors[start_index + varname_match.get_start("var")] = {"color": text_edit.theme_overrides.text_color} - if "attr" in varname_match.names: - colors[start_index + varname_match.get_start("attr")] = {"color": text_edit.theme_overrides.members_color} - colors[start_index + varname_match.get_end("attr")] = {"color": text_edit.theme_overrides.text_color} - if "key" in varname_match.names: - # Braces are outside of the key, so coloring them symbols_color - colors[start_index + varname_match.get_start("key") - 1] = {"color": text_edit.theme_overrides.symbols_color} - colors.merge(_get_literal_syntax_highlighting(start_index + varname_match.get_start("key"), varname_match.get_string("key")), true) - colors[start_index + varname_match.get_end("key")] = {"color": text_edit.theme_overrides.symbols_color} - - # Comparison operators. - var comparison_matches: Array[RegExMatch] = regex_comparison.search_all(text) - for comparison_match in comparison_matches: - colors.merge(_get_literal_syntax_highlighting(start_index + comparison_match.get_start("left"), comparison_match.get_string("left")), true) - colors[start_index + comparison_match.get_start("op")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + comparison_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} - var right = comparison_match.get_string("right") - if right.ends_with(":"): - right = right.substr(0, right.length() - 1) - colors.merge(_get_literal_syntax_highlighting(start_index + comparison_match.get_start("right"), right), true) - colors[start_index + comparison_match.get_start("right") + right.length()] = { "color": text_edit.theme_overrides.symbols_color } - - # Logical binary operators. - var blogical_matches: Array[RegExMatch] = regex_blogical.search_all(text) - for blogical_match in blogical_matches: - colors.merge(_get_literal_syntax_highlighting(start_index + blogical_match.get_start("left"), blogical_match.get_string("left")), true) - colors[start_index + blogical_match.get_start("op")] = {"color": text_edit.theme_overrides.conditions_color} - colors[start_index + blogical_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + blogical_match.get_start("right"), blogical_match.get_string("right")), true) - - # Logical unary operators. - var ulogical_matches: Array[RegExMatch] = regex_ulogical.search_all(text) - for ulogical_match in ulogical_matches: - colors[start_index + ulogical_match.get_start("op")] = {"color": text_edit.theme_overrides.conditions_color} - colors[start_index + ulogical_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + ulogical_match.get_start("right"), ulogical_match.get_string("right")), true) - - return colors - - -## Returns the syntax coloring for a list of literals separated by commas -func _get_list_syntax_highlighting(start_index: int, text: String) -> Dictionary: - var text_edit: TextEdit = get_text_edit() - var colors: Dictionary = {} - - # Comma-separated list of literals (for arrays and function arguments) - var element_matches: Array[RegExMatch] = regex_commas.search_all(text) - for element_match in element_matches: - colors.merge(_get_literal_syntax_highlighting(start_index + element_match.get_start(1), element_match.strings[1]), true) - - return colors diff --git a/addons/dialogue_manager/components/dialogue_cache.gd b/addons/dialogue_manager/components/dialogue_cache.gd deleted file mode 100644 index 5304d4b..0000000 --- a/addons/dialogue_manager/components/dialogue_cache.gd +++ /dev/null @@ -1,160 +0,0 @@ -extends Node - - -const DialogueConstants = preload("../constants.gd") -const DialogueSettings = preload("../settings.gd") -const DialogueManagerParseResult = preload("./parse_result.gd") - - -# Keeps track of errors and dependencies. -# { -# <dialogue file path> = { -# path = <dialogue file path>, -# dependencies = [<dialogue file path>, <dialogue file path>], -# errors = [<error>, <error>] -# } -# } -var _cache: Dictionary = {} - -var _update_dependency_timer: Timer = Timer.new() -var _update_dependency_paths: PackedStringArray = [] - - -func _ready() -> void: - add_child(_update_dependency_timer) - _update_dependency_timer.timeout.connect(_on_update_dependency_timeout) - - _build_cache() - - -func reimport_files(files: PackedStringArray = []) -> void: - if files.is_empty(): files = get_files() - - var file_system: EditorFileSystem = Engine.get_meta("DialogueManagerPlugin") \ - .get_editor_interface() \ - .get_resource_filesystem() - - # NOTE: Godot 4.2rc1 has an issue with reimporting more than one - # file at a time so we do them one by one - for file in files: - file_system.reimport_files([file]) - await get_tree().create_timer(0.2) - - -## Add a dialogue file to the cache. -func add_file(path: String, parse_results: DialogueManagerParseResult = null) -> void: - _cache[path] = { - path = path, - dependencies = [], - errors = [] - } - - if parse_results != null: - _cache[path].dependencies = Array(parse_results.imported_paths).filter(func(d): return d != path) - _cache[path].parsed_at = Time.get_ticks_msec() - - # If this is a fresh cache entry then we need to check for dependencies - if parse_results == null and not _update_dependency_paths.has(path): - queue_updating_dependencies(path) - - -## Get the file paths in the cache. -func get_files() -> PackedStringArray: - return _cache.keys() - - -## Remember any errors in a dialogue file. -func add_errors_to_file(path: String, errors: Array[Dictionary]) -> void: - if _cache.has(path): - _cache[path].errors = errors - else: - _cache[path] = { - path = path, - resource_path = "", - dependencies = [], - errors = errors - } - - -## Get a list of files that have errors in them. -func get_files_with_errors() -> Array[Dictionary]: - var files_with_errors: Array[Dictionary] = [] - for dialogue_file in _cache.values(): - if dialogue_file and dialogue_file.errors.size() > 0: - files_with_errors.append(dialogue_file) - return files_with_errors - - -## Queue a file to have it's dependencies checked -func queue_updating_dependencies(of_path: String) -> void: - _update_dependency_timer.stop() - if not _update_dependency_paths.has(of_path): - _update_dependency_paths.append(of_path) - _update_dependency_timer.start(0.5) - - -## Update any references to a file path that has moved -func move_file_path(from_path: String, to_path: String) -> void: - if not _cache.has(from_path): return - - if to_path != "": - _cache[to_path] = _cache[from_path].duplicate() - _cache.erase(from_path) - - -## Get any dialogue files that import a given path. -func get_files_with_dependency(imported_path: String) -> Array: - return _cache.values().filter(func(d): return d.dependencies.has(imported_path)) - - -## Get any paths that are dependent on a given path -func get_dependent_paths_for_reimport(on_path: String) -> PackedStringArray: - return get_files_with_dependency(on_path) \ - .filter(func(d): return Time.get_ticks_msec() - d.get("parsed_at", 0) > 3000) \ - .map(func(d): return d.path) - - -# Build the initial cache for dialogue files. -func _build_cache() -> void: - var current_files: PackedStringArray = _get_dialogue_files_in_filesystem() - for file in current_files: - add_file(file) - - -# Recursively find any dialogue files in a directory -func _get_dialogue_files_in_filesystem(path: String = "res://") -> PackedStringArray: - var files: PackedStringArray = [] - - if DirAccess.dir_exists_absolute(path): - var dir = DirAccess.open(path) - dir.list_dir_begin() - var file_name = dir.get_next() - while file_name != "": - var file_path: String = (path + "/" + file_name).simplify_path() - if dir.current_is_dir(): - if not file_name in [".godot", ".tmp"]: - files.append_array(_get_dialogue_files_in_filesystem(file_path)) - elif file_name.get_extension() == "dialogue": - files.append(file_path) - file_name = dir.get_next() - - return files - - -### Signals - - -func _on_update_dependency_timeout() -> void: - _update_dependency_timer.stop() - var import_regex: RegEx = RegEx.create_from_string("import \"(?<path>.*?)\"") - var file: FileAccess - var found_imports: Array[RegExMatch] - for path in _update_dependency_paths: - # Open the file and check for any "import" lines - file = FileAccess.open(path, FileAccess.READ) - found_imports = import_regex.search_all(file.get_as_text()) - var dependencies: PackedStringArray = [] - for found in found_imports: - dependencies.append(found.strings[found.names.path]) - _cache[path].dependencies = dependencies - _update_dependency_paths.clear() diff --git a/addons/dialogue_manager/components/download_update_panel.gd b/addons/dialogue_manager/components/download_update_panel.gd deleted file mode 100644 index 617d308..0000000 --- a/addons/dialogue_manager/components/download_update_panel.gd +++ /dev/null @@ -1,84 +0,0 @@ -@tool -extends Control - - -signal failed() -signal updated(updated_to_version: String) - - -const DialogueConstants = preload("../constants.gd") - -const TEMP_FILE_NAME = "user://temp.zip" - - -@onready var logo: TextureRect = %Logo -@onready var label: Label = $VBox/Label -@onready var http_request: HTTPRequest = $HTTPRequest -@onready var download_button: Button = %DownloadButton - -var next_version_release: Dictionary: - set(value): - next_version_release = value - label.text = DialogueConstants.translate(&"update.is_available_for_download") % value.tag_name.substr(1) - get: - return next_version_release - - -func _ready() -> void: - $VBox/Center/DownloadButton.text = DialogueConstants.translate(&"update.download_update") - $VBox/Center2/NotesButton.text = DialogueConstants.translate(&"update.release_notes") - - -### Signals - - -func _on_download_button_pressed() -> void: - # Safeguard the actual dialogue manager repo from accidentally updating itself - if FileAccess.file_exists("res://examples/test_scenes/test_scene.gd"): - prints("You can't update the addon from within itself.") - failed.emit() - return - - http_request.request(next_version_release.zipball_url) - download_button.disabled = true - download_button.text = DialogueConstants.translate(&"update.downloading") - - -func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void: - if result != HTTPRequest.RESULT_SUCCESS: - failed.emit() - return - - # Save the downloaded zip - var zip_file: FileAccess = FileAccess.open(TEMP_FILE_NAME, FileAccess.WRITE) - zip_file.store_buffer(body) - zip_file.close() - - OS.move_to_trash(ProjectSettings.globalize_path("res://addons/dialogue_manager")) - - var zip_reader: ZIPReader = ZIPReader.new() - zip_reader.open(TEMP_FILE_NAME) - var files: PackedStringArray = zip_reader.get_files() - - var base_path = files[1] - # Remove archive folder - files.remove_at(0) - # Remove assets folder - files.remove_at(0) - - for path in files: - var new_file_path: String = path.replace(base_path, "") - if path.ends_with("/"): - DirAccess.make_dir_recursive_absolute("res://addons/%s" % new_file_path) - else: - var file: FileAccess = FileAccess.open("res://addons/%s" % new_file_path, FileAccess.WRITE) - file.store_buffer(zip_reader.read_file(path)) - - zip_reader.close() - DirAccess.remove_absolute(TEMP_FILE_NAME) - - updated.emit(next_version_release.tag_name.substr(1)) - - -func _on_notes_button_pressed() -> void: - OS.shell_open(next_version_release.html_url) diff --git a/addons/dialogue_manager/components/download_update_panel.tscn b/addons/dialogue_manager/components/download_update_panel.tscn deleted file mode 100644 index f3f4523..0000000 --- a/addons/dialogue_manager/components/download_update_panel.tscn +++ /dev/null @@ -1,60 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://qdxrxv3c3hxk"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/download_update_panel.gd" id="1_4tm1k"] -[ext_resource type="Texture2D" uid="uid://d3baj6rygkb3f" path="res://addons/dialogue_manager/assets/update.svg" id="2_4o2m6"] - -[node name="DownloadUpdatePanel" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("1_4tm1k") - -[node name="HTTPRequest" type="HTTPRequest" parent="."] - -[node name="VBox" type="VBoxContainer" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = -1.0 -offset_top = 9.0 -offset_right = -1.0 -offset_bottom = 9.0 -grow_horizontal = 2 -grow_vertical = 2 -theme_override_constants/separation = 10 - -[node name="Logo" type="TextureRect" parent="VBox"] -unique_name_in_owner = true -clip_contents = true -custom_minimum_size = Vector2(300, 80) -layout_mode = 2 -texture = ExtResource("2_4o2m6") -stretch_mode = 5 - -[node name="Label" type="Label" parent="VBox"] -layout_mode = 2 -text = "v1.2.3 is available for download." -horizontal_alignment = 1 - -[node name="Center" type="CenterContainer" parent="VBox"] -layout_mode = 2 - -[node name="DownloadButton" type="Button" parent="VBox/Center"] -unique_name_in_owner = true -layout_mode = 2 -text = "Download update" - -[node name="Center2" type="CenterContainer" parent="VBox"] -layout_mode = 2 - -[node name="NotesButton" type="LinkButton" parent="VBox/Center2"] -layout_mode = 2 -text = "Read release notes" - -[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_request_completed"] -[connection signal="pressed" from="VBox/Center/DownloadButton" to="." method="_on_download_button_pressed"] -[connection signal="pressed" from="VBox/Center2/NotesButton" to="." method="_on_notes_button_pressed"] diff --git a/addons/dialogue_manager/components/errors_panel.gd b/addons/dialogue_manager/components/errors_panel.gd deleted file mode 100644 index f3e294d..0000000 --- a/addons/dialogue_manager/components/errors_panel.gd +++ /dev/null @@ -1,85 +0,0 @@ -@tool -extends HBoxContainer - - -signal error_pressed(line_number) - - -const DialogueConstants = preload("../constants.gd") - - -@onready var error_button: Button = $ErrorButton -@onready var next_button: Button = $NextButton -@onready var count_label: Label = $CountLabel -@onready var previous_button: Button = $PreviousButton - -## The index of the current error being shown -var error_index: int = 0: - set(next_error_index): - error_index = wrap(next_error_index, 0, errors.size()) - show_error() - get: - return error_index - -## The list of all errors -var errors: Array = []: - set(next_errors): - errors = next_errors - self.error_index = 0 - get: - return errors - - -func _ready() -> void: - apply_theme() - hide() - - -## Set up colors and icons -func apply_theme() -> void: - error_button.add_theme_color_override("font_color", get_theme_color("error_color", "Editor")) - error_button.add_theme_color_override("font_hover_color", get_theme_color("error_color", "Editor")) - error_button.icon = get_theme_icon("StatusError", "EditorIcons") - previous_button.icon = get_theme_icon("ArrowLeft", "EditorIcons") - next_button.icon = get_theme_icon("ArrowRight", "EditorIcons") - - -## Move the error index to match a given line -func show_error_for_line_number(line_number: int) -> void: - for i in range(0, errors.size()): - if errors[i].line_number == line_number: - self.error_index = i - - -## Show the current error -func show_error() -> void: - if errors.size() == 0: - hide() - else: - show() - count_label.text = DialogueConstants.translate(&"n_of_n").format({ index = error_index + 1, total = errors.size() }) - var error = errors[error_index] - error_button.text = DialogueConstants.translate(&"errors.line_and_message").format({ line = error.line_number + 1, column = error.column_number, message = DialogueConstants.get_error_message(error.error) }) - if error.has("external_error"): - error_button.text += " " + DialogueConstants.get_error_message(error.external_error) - - -### Signals - - -func _on_errors_panel_theme_changed() -> void: - apply_theme() - - -func _on_error_button_pressed() -> void: - emit_signal("error_pressed", errors[error_index].line_number, errors[error_index].column_number) - - -func _on_previous_button_pressed() -> void: - self.error_index -= 1 - _on_error_button_pressed() - - -func _on_next_button_pressed() -> void: - self.error_index += 1 - _on_error_button_pressed() diff --git a/addons/dialogue_manager/components/errors_panel.tscn b/addons/dialogue_manager/components/errors_panel.tscn deleted file mode 100644 index 956552b..0000000 --- a/addons/dialogue_manager/components/errors_panel.tscn +++ /dev/null @@ -1,56 +0,0 @@ -[gd_scene load_steps=4 format=3 uid="uid://cs8pwrxr5vxix"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/errors_panel.gd" id="1_nfm3c"] - -[sub_resource type="Image" id="Image_wy5pj"] -data = { -"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), -"format": "RGBA8", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_s6fxl"] -image = SubResource("Image_wy5pj") - -[node name="ErrorsPanel" type="HBoxContainer"] -visible = false -offset_right = 1024.0 -offset_bottom = 600.0 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("1_nfm3c") -metadata/_edit_layout_mode = 1 - -[node name="ErrorButton" type="Button" parent="."] -layout_mode = 2 -size_flags_horizontal = 3 -theme_override_colors/font_color = Color(0, 0, 0, 1) -theme_override_colors/font_hover_color = Color(0, 0, 0, 1) -theme_override_constants/h_separation = 3 -icon = SubResource("ImageTexture_s6fxl") -flat = true -alignment = 0 -text_overrun_behavior = 4 - -[node name="Spacer" type="Control" parent="."] -custom_minimum_size = Vector2(40, 0) -layout_mode = 2 - -[node name="PreviousButton" type="Button" parent="."] -layout_mode = 2 -icon = SubResource("ImageTexture_s6fxl") -flat = true - -[node name="CountLabel" type="Label" parent="."] -layout_mode = 2 - -[node name="NextButton" type="Button" parent="."] -layout_mode = 2 -icon = SubResource("ImageTexture_s6fxl") -flat = true - -[connection signal="pressed" from="ErrorButton" to="." method="_on_error_button_pressed"] -[connection signal="pressed" from="PreviousButton" to="." method="_on_previous_button_pressed"] -[connection signal="pressed" from="NextButton" to="." method="_on_next_button_pressed"] diff --git a/addons/dialogue_manager/components/files_list.gd b/addons/dialogue_manager/components/files_list.gd deleted file mode 100644 index ac4793d..0000000 --- a/addons/dialogue_manager/components/files_list.gd +++ /dev/null @@ -1,144 +0,0 @@ -@tool -extends VBoxContainer - - -signal file_selected(file_path: String) -signal file_popup_menu_requested(at_position: Vector2) -signal file_double_clicked(file_path: String) -signal file_middle_clicked(file_path: String) - - -const DialogueConstants = preload("../constants.gd") - -const MODIFIED_SUFFIX = "(*)" - - -@export var icon: Texture2D - -@onready var filter_edit: LineEdit = $FilterEdit -@onready var list: ItemList = $List - -var file_map: Dictionary = {} - -var current_file_path: String = "" - -var files: PackedStringArray = []: - set(next_files): - files = next_files - files.sort() - update_file_map() - apply_filter() - get: - return files - -var unsaved_files: Array[String] = [] - -var filter: String: - set(next_filter): - filter = next_filter - apply_filter() - get: - return filter - - -func _ready() -> void: - apply_theme() - - filter_edit.placeholder_text = DialogueConstants.translate(&"files_list.filter") - - -func select_file(file: String) -> void: - list.deselect_all() - for i in range(0, list.get_item_count()): - var item_text = list.get_item_text(i).replace(MODIFIED_SUFFIX, "") - if item_text == get_nice_file(file, item_text.count("/") + 1): - list.select(i) - - -func mark_file_as_unsaved(file: String, is_unsaved: bool) -> void: - if not file in unsaved_files and is_unsaved: - unsaved_files.append(file) - elif file in unsaved_files and not is_unsaved: - unsaved_files.erase(file) - apply_filter() - - -func update_file_map() -> void: - file_map = {} - for file in files: - var nice_file: String = get_nice_file(file) - - # See if a value with just the file name is already in the map - for key in file_map.keys(): - if file_map[key] == nice_file: - var bit_count = nice_file.count("/") + 2 - - var existing_nice_file = get_nice_file(key, bit_count) - nice_file = get_nice_file(file, bit_count) - - while nice_file == existing_nice_file: - bit_count += 1 - existing_nice_file = get_nice_file(key, bit_count) - nice_file = get_nice_file(file, bit_count) - - file_map[key] = existing_nice_file - - file_map[file] = nice_file - - -func get_nice_file(file_path: String, path_bit_count: int = 1) -> String: - var bits = file_path.replace("res://", "").replace(".dialogue", "").split("/") - bits = bits.slice(-path_bit_count) - return "/".join(bits) - - -func apply_filter() -> void: - list.clear() - for file in file_map.keys(): - if filter == "" or filter.to_lower() in file.to_lower(): - var nice_file = file_map[file] - if file in unsaved_files: - nice_file += MODIFIED_SUFFIX - var new_id := list.add_item(nice_file) - list.set_item_icon(new_id, icon) - - select_file(current_file_path) - - -func apply_theme() -> void: - if is_instance_valid(filter_edit): - filter_edit.right_icon = get_theme_icon("Search", "EditorIcons") - - -### Signals - - -func _on_theme_changed() -> void: - apply_theme() - - -func _on_filter_edit_text_changed(new_text: String) -> void: - self.filter = new_text - - -func _on_list_item_clicked(index: int, at_position: Vector2, mouse_button_index: int) -> void: - if mouse_button_index == MOUSE_BUTTON_LEFT: - var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") - var file = file_map.find_key(item_text) - select_file(file) - file_selected.emit(file) - - if mouse_button_index == MOUSE_BUTTON_RIGHT: - file_popup_menu_requested.emit(at_position) - - if mouse_button_index == MOUSE_BUTTON_MIDDLE: - var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") - var file = file_map.find_key(item_text) - file_middle_clicked.emit(file) - - -func _on_list_item_activated(index: int) -> void: - var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") - var file = file_map.find_key(item_text) - select_file(file) - file_double_clicked.emit(file) diff --git a/addons/dialogue_manager/components/files_list.tscn b/addons/dialogue_manager/components/files_list.tscn deleted file mode 100644 index 12bee0b..0000000 --- a/addons/dialogue_manager/components/files_list.tscn +++ /dev/null @@ -1,40 +0,0 @@ -[gd_scene load_steps=5 format=3 uid="uid://dnufpcdrreva3"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/files_list.gd" id="1_cytii"] -[ext_resource type="Texture2D" uid="uid://d3lr2uas6ax8v" path="res://addons/dialogue_manager/assets/icon.svg" id="2_3ijx1"] - -[sub_resource type="Image" id="Image_h3jns"] -data = { -"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), -"format": "RGBA8", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_44sbr"] -image = SubResource("Image_h3jns") - -[node name="FilesList" type="VBoxContainer"] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("1_cytii") -icon = ExtResource("2_3ijx1") - -[node name="FilterEdit" type="LineEdit" parent="."] -layout_mode = 2 -placeholder_text = "Filter files" -clear_button_enabled = true -right_icon = SubResource("ImageTexture_44sbr") - -[node name="List" type="ItemList" parent="."] -layout_mode = 2 -size_flags_vertical = 3 - -[connection signal="theme_changed" from="." to="." method="_on_theme_changed"] -[connection signal="text_changed" from="FilterEdit" to="." method="_on_filter_edit_text_changed"] -[connection signal="item_activated" from="List" to="." method="_on_list_item_activated"] -[connection signal="item_clicked" from="List" to="." method="_on_list_item_clicked"] diff --git a/addons/dialogue_manager/components/find_in_files.gd b/addons/dialogue_manager/components/find_in_files.gd deleted file mode 100644 index 916b744..0000000 --- a/addons/dialogue_manager/components/find_in_files.gd +++ /dev/null @@ -1,229 +0,0 @@ -@tool -extends Control - -signal result_selected(path: String, cursor: Vector2, length: int) - - -const DialogueConstants = preload("../constants.gd") - - -@export var main_view: Control -@export var code_edit: CodeEdit - -@onready var input: LineEdit = %Input -@onready var search_button: Button = %SearchButton -@onready var match_case_button: CheckBox = %MatchCaseButton -@onready var replace_toggle: CheckButton = %ReplaceToggle -@onready var replace_container: VBoxContainer = %ReplaceContainer -@onready var replace_input: LineEdit = %ReplaceInput -@onready var replace_selected_button: Button = %ReplaceSelectedButton -@onready var replace_all_button: Button = %ReplaceAllButton -@onready var results_container: VBoxContainer = %ResultsContainer -@onready var result_template: HBoxContainer = %ResultTemplate - -var current_results: Dictionary = {}: - set(value): - current_results = value - update_results_view() - if current_results.size() == 0: - replace_selected_button.disabled = true - replace_all_button.disabled = true - else: - replace_selected_button.disabled = false - replace_all_button.disabled = false - get: - return current_results - -var selections: PackedStringArray = [] - - -func prepare() -> void: - input.grab_focus() - - var template_label = result_template.get_node("Label") - template_label.get_theme_stylebox(&"focus").bg_color = code_edit.theme_overrides.current_line_color - template_label.add_theme_font_override(&"normal_font", code_edit.get_theme_font(&"font")) - - replace_toggle.set_pressed_no_signal(false) - replace_container.hide() - - $VBoxContainer/HBoxContainer/FindContainer/Label.text = DialogueConstants.translate(&"search.find") - input.placeholder_text = DialogueConstants.translate(&"search.placeholder") - input.text = "" - search_button.text = DialogueConstants.translate(&"search.find_all") - match_case_button.text = DialogueConstants.translate(&"search.match_case") - replace_toggle.text = DialogueConstants.translate(&"search.toggle_replace") - $VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceLabel.text = DialogueConstants.translate(&"search.replace_with") - replace_input.placeholder_text = DialogueConstants.translate(&"search.replace_placeholder") - replace_input.text = "" - replace_all_button.text = DialogueConstants.translate(&"search.replace_all") - replace_selected_button.text = DialogueConstants.translate(&"search.replace_selected") - - selections.clear() - self.current_results = {} - -#region helpers - - -func update_results_view() -> void: - for child in results_container.get_children(): - child.queue_free() - - for path in current_results.keys(): - var path_label: Label = Label.new() - path_label.text = path - # Show open files - if main_view.open_buffers.has(path): - path_label.text += "(*)" - results_container.add_child(path_label) - for path_result in current_results.get(path): - var result_item: HBoxContainer = result_template.duplicate() - - var checkbox: CheckBox = result_item.get_node("CheckBox") as CheckBox - var key: String = get_selection_key(path, path_result) - checkbox.toggled.connect(func(is_pressed): - if is_pressed: - if not selections.has(key): - selections.append(key) - else: - if selections.has(key): - selections.remove_at(selections.find(key)) - ) - checkbox.set_pressed_no_signal(selections.has(key)) - checkbox.visible = replace_toggle.button_pressed - - var result_label: RichTextLabel = result_item.get_node("Label") as RichTextLabel - var colors: Dictionary = code_edit.theme_overrides - var highlight: String = "" - if replace_toggle.button_pressed: - var matched_word: String = "[bgcolor=" + colors.critical_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + path_result.matched_text + "[/color][/bgcolor]" - highlight = "[s]" + matched_word + "[/s][bgcolor=" + colors.notice_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + replace_input.text + "[/color][/bgcolor]" - else: - highlight = "[bgcolor=" + colors.symbols_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + path_result.matched_text + "[/color][/bgcolor]" - var text: String = path_result.text.substr(0, path_result.index) + highlight + path_result.text.substr(path_result.index + path_result.query.length()) - result_label.text = "%s: %s" % [str(path_result.line).lpad(4), text] - result_label.gui_input.connect(func(event): - if event is InputEventMouseButton and (event as InputEventMouseButton).button_index == MOUSE_BUTTON_LEFT and (event as InputEventMouseButton).double_click: - result_selected.emit(path, Vector2(path_result.index, path_result.line), path_result.query.length()) - ) - - results_container.add_child(result_item) - - -func find_in_files() -> Dictionary: - var results: Dictionary = {} - - var q: String = input.text - var cache = Engine.get_meta("DialogueCache") - var file: FileAccess - for path in cache.get_files(): - var path_results: Array = [] - var lines: PackedStringArray = [] - - if main_view.open_buffers.has(path): - lines = main_view.open_buffers.get(path).text.split("\n") - else: - file = FileAccess.open(path, FileAccess.READ) - lines = file.get_as_text().split("\n") - - for i in range(0, lines.size()): - var index: int = find_in_line(lines[i], q) - while index > -1: - path_results.append({ - line = i, - index = index, - text = lines[i], - matched_text = lines[i].substr(index, q.length()), - query = q - }) - index = find_in_line(lines[i], q, index + q.length()) - - if file != null and file.is_open(): - file.close() - - if path_results.size() > 0: - results[path] = path_results - - return results - - -func get_selection_key(path: String, path_result: Dictionary) -> String: - return "%s-%d-%d" % [path, path_result.line, path_result.index] - - -func find_in_line(line: String, query: String, from_index: int = 0) -> int: - if match_case_button.button_pressed: - return line.find(query, from_index) - else: - return line.findn(query, from_index) - - -func replace_results(only_selected: bool) -> void: - var file: FileAccess - var lines: PackedStringArray = [] - for path in current_results: - if main_view.open_buffers.has(path): - lines = main_view.open_buffers.get(path).text.split("\n") - else: - file = FileAccess.open(path, FileAccess.READ_WRITE) - lines = file.get_as_text().split("\n") - - # Read the results in reverse because we're going to be modifying them as we go - var path_results: Array = current_results.get(path).duplicate() - path_results.reverse() - for path_result in path_results: - var key: String = get_selection_key(path, path_result) - if not only_selected or (only_selected and selections.has(key)): - lines[path_result.line] = lines[path_result.line].substr(0, path_result.index) + replace_input.text + lines[path_result.line].substr(path_result.index + path_result.matched_text.length()) - - var replaced_text: String = "\n".join(lines) - if file != null and file.is_open(): - file.seek(0) - file.store_string(replaced_text) - file.close() - else: - main_view.open_buffers.get(path).text = replaced_text - if main_view.current_file_path == path: - code_edit.text = replaced_text - - current_results = find_in_files() - - -#endregion - -#region signals - - -func _on_search_button_pressed() -> void: - selections.clear() - self.current_results = find_in_files() - - -func _on_input_text_submitted(new_text: String) -> void: - _on_search_button_pressed() - - -func _on_replace_toggle_toggled(toggled_on: bool) -> void: - replace_container.visible = toggled_on - if toggled_on: - replace_input.grab_focus() - update_results_view() - - -func _on_replace_input_text_changed(new_text: String) -> void: - update_results_view() - - -func _on_replace_selected_button_pressed() -> void: - replace_results(true) - - -func _on_replace_all_button_pressed() -> void: - replace_results(false) - - -func _on_match_case_button_toggled(toggled_on: bool) -> void: - _on_search_button_pressed() - - -#endregion diff --git a/addons/dialogue_manager/components/find_in_files.tscn b/addons/dialogue_manager/components/find_in_files.tscn deleted file mode 100644 index 8aaef4b..0000000 --- a/addons/dialogue_manager/components/find_in_files.tscn +++ /dev/null @@ -1,139 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://0n7hwviyyly4"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/find_in_files.gd" id="1_3xicy"] - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_owohg"] -bg_color = Color(0.266667, 0.278431, 0.352941, 0.243137) -corner_detail = 1 - -[node name="FindInFiles" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -script = ExtResource("1_3xicy") - -[node name="VBoxContainer" type="VBoxContainer" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] -layout_mode = 2 - -[node name="FindContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/FindContainer"] -layout_mode = 2 -text = "Find:" - -[node name="Input" type="LineEdit" parent="VBoxContainer/HBoxContainer/FindContainer"] -unique_name_in_owner = true -layout_mode = 2 -clear_button_enabled = true - -[node name="FindToolbar" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/FindContainer"] -layout_mode = 2 - -[node name="SearchButton" type="Button" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Find all..." - -[node name="MatchCaseButton" type="CheckBox" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Match case" - -[node name="Control" type="Control" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="ReplaceToggle" type="CheckButton" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Replace" - -[node name="ReplaceContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="ReplaceLabel" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] -layout_mode = 2 -text = "Replace with:" - -[node name="ReplaceInput" type="LineEdit" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_horizontal = 3 -clear_button_enabled = true - -[node name="ReplaceToolbar" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] -layout_mode = 2 - -[node name="ReplaceSelectedButton" type="Button" parent="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Replace selected" - -[node name="ReplaceAllButton" type="Button" parent="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Replace all" - -[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer"] -layout_mode = 2 - -[node name="ReplaceToolbar" type="HBoxContainer" parent="VBoxContainer/VBoxContainer"] -layout_mode = 2 - -[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 3 -follow_focus = true - -[node name="ResultsContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -theme_override_constants/separation = 0 - -[node name="ResultTemplate" type="HBoxContainer" parent="."] -unique_name_in_owner = true -layout_mode = 0 -offset_left = 155.0 -offset_top = -74.0 -offset_right = 838.0 -offset_bottom = -51.0 - -[node name="CheckBox" type="CheckBox" parent="ResultTemplate"] -layout_mode = 2 - -[node name="Label" type="RichTextLabel" parent="ResultTemplate"] -layout_mode = 2 -size_flags_horizontal = 3 -focus_mode = 2 -theme_override_styles/focus = SubResource("StyleBoxFlat_owohg") -bbcode_enabled = true -text = "Result" -fit_content = true -scroll_active = false - -[connection signal="text_submitted" from="VBoxContainer/HBoxContainer/FindContainer/Input" to="." method="_on_input_text_submitted"] -[connection signal="pressed" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/SearchButton" to="." method="_on_search_button_pressed"] -[connection signal="toggled" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/MatchCaseButton" to="." method="_on_match_case_button_toggled"] -[connection signal="toggled" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/ReplaceToggle" to="." method="_on_replace_toggle_toggled"] -[connection signal="text_changed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceInput" to="." method="_on_replace_input_text_changed"] -[connection signal="pressed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar/ReplaceSelectedButton" to="." method="_on_replace_selected_button_pressed"] -[connection signal="pressed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar/ReplaceAllButton" to="." method="_on_replace_all_button_pressed"] diff --git a/addons/dialogue_manager/components/parse_result.gd b/addons/dialogue_manager/components/parse_result.gd deleted file mode 100644 index d467cb9..0000000 --- a/addons/dialogue_manager/components/parse_result.gd +++ /dev/null @@ -1,10 +0,0 @@ -class_name DialogueManagerParseResult extends RefCounted - -var imported_paths: PackedStringArray = [] -var using_states: PackedStringArray = [] -var titles: Dictionary = {} -var character_names: PackedStringArray = [] -var first_title: String = "" -var lines: Dictionary = {} -var errors: Array[Dictionary] = [] -var raw_text: String = "" diff --git a/addons/dialogue_manager/components/parser.gd b/addons/dialogue_manager/components/parser.gd deleted file mode 100644 index ad6e3ac..0000000 --- a/addons/dialogue_manager/components/parser.gd +++ /dev/null @@ -1,1780 +0,0 @@ -@tool - -class_name DialogueManagerParser extends Object - - -const DialogueConstants = preload("../constants.gd") -const DialogueSettings = preload("../settings.gd") -const ResolvedLineData = preload("./resolved_line_data.gd") -const ResolvedTagData = preload("./resolved_tag_data.gd") -const DialogueManagerParseResult = preload("./parse_result.gd") - - -var IMPORT_REGEX: RegEx = RegEx.create_from_string("import \"(?<path>[^\"]+)\" as (?<prefix>[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+)") -var USING_REGEX: RegEx = RegEx.create_from_string("using (?<state>.*)") -var VALID_TITLE_REGEX: RegEx = RegEx.create_from_string("^[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+$") -var BEGINS_WITH_NUMBER_REGEX: RegEx = RegEx.create_from_string("^\\d") -var TRANSLATION_REGEX: RegEx = RegEx.create_from_string("\\[ID:(?<tr>.*?)\\]") -var TAGS_REGEX: RegEx = RegEx.create_from_string("\\[#(?<tags>.*?)\\]") -var MUTATION_REGEX: RegEx = RegEx.create_from_string("(?<keyword>do|do!|set) (?<mutation>.*)") -var CONDITION_REGEX: RegEx = RegEx.create_from_string("(if|elif|while|else if) (?<condition>.*)") -var WRAPPED_CONDITION_REGEX: RegEx = RegEx.create_from_string("\\[if (?<condition>.*)\\]") -var REPLACEMENTS_REGEX: RegEx = RegEx.create_from_string("{{(.*?)}}") -var GOTO_REGEX: RegEx = RegEx.create_from_string("=><? (?<jump_to_title>.*)") -var INDENT_REGEX: RegEx = RegEx.create_from_string("^\\t+") -var INLINE_RANDOM_REGEX: RegEx = RegEx.create_from_string("\\[\\[(?<options>.*?)\\]\\]") -var INLINE_CONDITIONALS_REGEX: RegEx = RegEx.create_from_string("\\[if (?<condition>.+?)\\](?<body>.*?)\\[\\/if\\]") - -var TOKEN_DEFINITIONS: Dictionary = { - DialogueConstants.TOKEN_FUNCTION: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*\\("), - DialogueConstants.TOKEN_DICTIONARY_REFERENCE: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*\\["), - DialogueConstants.TOKEN_PARENS_OPEN: RegEx.create_from_string("^\\("), - DialogueConstants.TOKEN_PARENS_CLOSE: RegEx.create_from_string("^\\)"), - DialogueConstants.TOKEN_BRACKET_OPEN: RegEx.create_from_string("^\\["), - DialogueConstants.TOKEN_BRACKET_CLOSE: RegEx.create_from_string("^\\]"), - DialogueConstants.TOKEN_BRACE_OPEN: RegEx.create_from_string("^\\{"), - DialogueConstants.TOKEN_BRACE_CLOSE: RegEx.create_from_string("^\\}"), - DialogueConstants.TOKEN_COLON: RegEx.create_from_string("^:"), - DialogueConstants.TOKEN_COMPARISON: RegEx.create_from_string("^(==|<=|>=|<|>|!=|in )"), - DialogueConstants.TOKEN_ASSIGNMENT: RegEx.create_from_string("^(\\+=|\\-=|\\*=|/=|=)"), - DialogueConstants.TOKEN_NUMBER: RegEx.create_from_string("^\\-?\\d+(\\.\\d+)?"), - DialogueConstants.TOKEN_OPERATOR: RegEx.create_from_string("^(\\+|\\-|\\*|/|%)"), - DialogueConstants.TOKEN_COMMA: RegEx.create_from_string("^,"), - DialogueConstants.TOKEN_DOT: RegEx.create_from_string("^\\."), - DialogueConstants.TOKEN_STRING: RegEx.create_from_string("^(\".*?\"|\'.*?\')"), - DialogueConstants.TOKEN_NOT: RegEx.create_from_string("^(not( |$)|!)"), - DialogueConstants.TOKEN_AND_OR: RegEx.create_from_string("^(and|or)( |$)"), - DialogueConstants.TOKEN_VARIABLE: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*"), - DialogueConstants.TOKEN_COMMENT: RegEx.create_from_string("^#.*"), - DialogueConstants.TOKEN_CONDITION: RegEx.create_from_string("^(if|elif|else)"), - DialogueConstants.TOKEN_BOOL: RegEx.create_from_string("^(true|false)") -} - -var WEIGHTED_RANDOM_SIBLINGS_REGEX: RegEx = RegEx.create_from_string("^\\%(?<weight>[\\d.]+)? ") - -var raw_lines: PackedStringArray = [] -var parent_stack: Array[String] = [] - -var parsed_lines: Dictionary = {} -var imported_paths: PackedStringArray = [] -var using_states: PackedStringArray = [] -var titles: Dictionary = {} -var character_names: PackedStringArray = [] -var first_title: String = "" -var errors: Array[Dictionary] = [] -var raw_text: String = "" - -var _imported_line_map: Dictionary = {} -var _imported_line_count: int = 0 - -var while_loopbacks: Array[String] = [] - - -## Parse some raw dialogue text. Returns a dictionary containing parse results -static func parse_string(string: String, path: String) -> DialogueManagerParseResult: - var parser: DialogueManagerParser = DialogueManagerParser.new() - var error: Error = parser.parse(string, path) - var data: DialogueManagerParseResult = parser.get_data() - parser.free() - - if error == OK: - return data - else: - return null - - -## Extract bbcode and other markers from a string -static func extract_markers_from_string(string: String) -> ResolvedLineData: - var parser: DialogueManagerParser = DialogueManagerParser.new() - var markers: ResolvedLineData = parser.extract_markers(string) - parser.free() - - return markers - - -## Parse some raw dialogue text. Returns a dictionary containing parse results -func parse(text: String, path: String) -> Error: - prepare(text, path) - raw_text = text - - # Parse all of the content - var known_translations = {} - - # Get list of known autoloads - var autoload_names: PackedStringArray = get_autoload_names() - - # Keep track of the last doc comment - var doc_comments: Array[String] = [] - - # Then parse all lines - for id in range(0, raw_lines.size()): - var raw_line: String = raw_lines[id] - - var line: Dictionary = { - id = str(id), - next_id = DialogueConstants.ID_NULL - } - - # Work out if we are inside a conditional or option or if we just - # indented back out of one - var indent_size: int = get_indent(raw_line) - if indent_size < parent_stack.size() and not is_line_empty(raw_line): - for _tab in range(0, parent_stack.size() - indent_size): - parent_stack.pop_back() - - # If we are indented then this line should know about its parent - if parent_stack.size() > 0: - line["parent_id"] = parent_stack.back() - - # Trim any indentation (now that we've calculated it) so we can check - # the begining of each line for its type - raw_line = raw_line.strip_edges(true, false) - - # Grab translations - var translation_key: String = extract_translation(raw_line) - if translation_key != "": - line["translation_key"] = translation_key - raw_line = raw_line.replace("[ID:%s]" % translation_key, "") - - # Check for each kind of line - - # Start shortcuts - if raw_line.begins_with("using "): - var using_match: RegExMatch = USING_REGEX.search(raw_line) - if "state" in using_match.names: - var using_state: String = using_match.strings[using_match.names.state].strip_edges() - if not using_state in autoload_names: - add_error(id, 0, DialogueConstants.ERR_UNKNOWN_USING) - elif not using_state in using_states: - using_states.append(using_state) - continue - - # Response - elif is_response_line(raw_line): - # Add any doc notes - line["notes"] = "\n".join(doc_comments) - doc_comments = [] - - parent_stack.append(str(id)) - line["type"] = DialogueConstants.TYPE_RESPONSE - - # Extract any #tags - var tag_data: ResolvedTagData = extract_tags(raw_line) - line["tags"] = tag_data.tags - raw_line = tag_data.line_without_tags - - if " [if " in raw_line: - line["condition"] = extract_condition(raw_line, true, indent_size) - if " =>" in raw_line: - line["next_id"] = extract_goto(raw_line) - if " =><" in raw_line: - # Because of when the return point needs to be known at runtime we need to split - # this line into two (otherwise the return point would be dependent on the balloon) - var goto_line: Dictionary = { - type = DialogueConstants.TYPE_GOTO, - next_id = extract_goto(raw_line), - next_id_after = find_next_line_after_responses(id), - is_snippet = true - } - parsed_lines[str(id) + ".1"] = goto_line - line["next_id"] = str(id) + ".1" - - # Make sure the added goto line can actually go to somewhere - if goto_line.next_id in [DialogueConstants.ID_ERROR, DialogueConstants.ID_ERROR_INVALID_TITLE, DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY]: - line["next_id"] = goto_line.next_id - - line["character"] = "" - line["character_replacements"] = [] as Array[Dictionary] - line["text"] = extract_response_prompt(raw_line) - - var previous_response_id = find_previous_response_id(id) - if parsed_lines.has(previous_response_id): - var previous_response = parsed_lines[previous_response_id] - # Add this response to the list on the first response so that it is the - # authority on what is in the list of responses - previous_response["responses"] = previous_response["responses"] + PackedStringArray([str(id)]) - else: - # No previous response so this is the first in the list - line["responses"] = PackedStringArray([str(id)]) - - line["next_id_after"] = find_next_line_after_responses(id) - - # If this response has no body then the next id is the next id after - if not line.has("next_id") or line.next_id == DialogueConstants.ID_NULL: - var next_nonempty_line_id = get_next_nonempty_line_id(id) - if next_nonempty_line_id != DialogueConstants.ID_NULL: - if get_indent(raw_lines[next_nonempty_line_id.to_int()]) <= indent_size: - line["next_id"] = line.next_id_after - else: - line["next_id"] = next_nonempty_line_id - - line["text_replacements"] = extract_dialogue_replacements(line.get("text"), indent_size + 2) - for replacement in line.text_replacements: - if replacement.has("error"): - add_error(id, replacement.index, replacement.error) - - # If this response has a character name in it then it will automatically be - # injected as a line of dialogue if the player selects it - var response_text: String = line.text.replace("\\:", "!ESCAPED_COLON!") - if ": " in response_text: - if DialogueSettings.get_setting("create_lines_for_responses_with_characters", true): - var first_child: Dictionary = { - type = DialogueConstants.TYPE_DIALOGUE, - next_id = line.next_id, - next_id_after = line.next_id_after, - text_replacements = line.text_replacements, - tags = line.tags, - translation_key = line.get("translation_key") - } - parse_response_character_and_text(id, response_text, first_child, indent_size, parsed_lines) - line["character"] = first_child.character - line["character_replacements"] = first_child.character_replacements - line["text"] = first_child.text - line["translation_key"] = first_child.translation_key - parsed_lines[str(id) + ".2"] = first_child - line["next_id"] = str(id) + ".2" - else: - parse_response_character_and_text(id, response_text, line, indent_size, parsed_lines) - else: - line["text"] = response_text.replace("!ESCAPED_COLON!", ":") - - # Title - elif is_title_line(raw_line): - line["type"] = DialogueConstants.TYPE_TITLE - if not raw_lines[id].begins_with("~"): - add_error(id, indent_size + 2, DialogueConstants.ERR_NESTED_TITLE) - else: - line["text"] = extract_title(raw_line) - # Titles can't have numbers as the first letter (unless they are external titles which get replaced with hashes) - if id >= _imported_line_count and BEGINS_WITH_NUMBER_REGEX.search(line.text): - add_error(id, 2, DialogueConstants.ERR_TITLE_BEGINS_WITH_NUMBER) - # Only import titles are allowed to have "/" in them - var valid_title = VALID_TITLE_REGEX.search(raw_line.replace("/", "").substr(2).strip_edges()) - if not valid_title: - add_error(id, 2, DialogueConstants.ERR_TITLE_INVALID_CHARACTERS) - - # Condition - elif is_condition_line(raw_line, false): - parent_stack.append(str(id)) - line["type"] = DialogueConstants.TYPE_CONDITION - line["condition"] = extract_condition(raw_line, false, indent_size) - line["next_id_after"] = find_next_line_after_conditions(id) - var next_sibling_id = find_next_condition_sibling(id) - line["next_conditional_id"] = next_sibling_id if is_valid_id(next_sibling_id) else line.next_id_after - - elif is_condition_line(raw_line, true): - parent_stack.append(str(id)) - line["type"] = DialogueConstants.TYPE_CONDITION - line["next_id_after"] = find_next_line_after_conditions(id) - line["next_conditional_id"] = line["next_id_after"] - - elif is_while_condition_line(raw_line): - parent_stack.append(str(id)) - line["type"] = DialogueConstants.TYPE_CONDITION - line["condition"] = extract_condition(raw_line, false, indent_size) - line["next_id_after"] = find_next_line_after_conditions(id) - while_loopbacks.append(find_last_line_within_conditions(id)) - line["next_conditional_id"] = line["next_id_after"] - - # Mutation - elif is_mutation_line(raw_line): - line["type"] = DialogueConstants.TYPE_MUTATION - line["mutation"] = extract_mutation(raw_line) - - # Goto - elif is_goto_line(raw_line): - line["type"] = DialogueConstants.TYPE_GOTO - - if raw_line.begins_with("%"): - apply_weighted_random(id, raw_line, indent_size, line) - - line["next_id"] = extract_goto(raw_line) - if is_goto_snippet_line(raw_line): - line["is_snippet"] = true - line["next_id_after"] = get_line_after_line(id, indent_size, line) - else: - line["is_snippet"] = false - - # Nested dialogue - elif is_nested_dialogue_line(raw_line, parsed_lines, raw_lines, indent_size): - var parent_line: Dictionary = parsed_lines.values().back() - var parent_indent_size: int = get_indent(raw_lines[parent_line.id.to_int()]) - var should_update_translation_key: bool = parent_line.translation_key == parent_line.text - var suffix: String = raw_line.strip_edges(true, false) - if suffix == "": - suffix = " " - parent_line["text"] += "\n" + suffix - parent_line["text_replacements"] = extract_dialogue_replacements(parent_line.text, parent_line.character.length() + 2 + parent_indent_size) - for replacement in parent_line.text_replacements: - if replacement.has("error"): - add_error(id, replacement.index, replacement.error) - - if should_update_translation_key: - parent_line["translation_key"] = parent_line.text - - parent_line["next_id"] = get_line_after_line(id, parent_indent_size, parent_line) - - # Ignore this line when checking for indent errors - remove_error(parent_line.id.to_int(), DialogueConstants.ERR_INVALID_INDENTATION) - - var next_line = raw_lines[parent_line.next_id.to_int()] - if not is_dialogue_line(next_line) and get_indent(next_line) >= indent_size: - add_error(parent_line.next_id.to_int(), indent_size, DialogueConstants.ERR_INVALID_INDENTATION) - - continue - - elif raw_line.strip_edges().begins_with("##"): - doc_comments.append(raw_line.replace("##", "").strip_edges()) - continue - - elif is_line_empty(raw_line) or is_import_line(raw_line): - continue - - # Regular dialogue - else: - # Remove escape character - if raw_line.begins_with("\\using"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\if"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\elif"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\else"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\while"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\-"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\~"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\=>"): raw_line = raw_line.substr(1) - - # Add any doc notes - line["notes"] = "\n".join(doc_comments) - doc_comments = [] - - # Work out any weighted random siblings - if raw_line.begins_with("%"): - apply_weighted_random(id, raw_line, indent_size, line) - raw_line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_line, "") - - line["type"] = DialogueConstants.TYPE_DIALOGUE - - # Extract any tags before we process the line - var tag_data: ResolvedTagData = extract_tags(raw_line) - line["tags"] = tag_data.tags - raw_line = tag_data.line_without_tags - - var l = raw_line.replace("\\:", "!ESCAPED_COLON!") - if ": " in l: - var bits = Array(l.strip_edges().split(": ")) - line["character"] = bits.pop_front().strip_edges() - if not line["character"] in character_names: - character_names.append(line["character"]) - # You can use variables in the character's name - line["character_replacements"] = extract_dialogue_replacements(line.character, indent_size) - for replacement in line.character_replacements: - if replacement.has("error"): - add_error(id, replacement.index, replacement.error) - line["text"] = ": ".join(bits).replace("!ESCAPED_COLON!", ":") - else: - line["character"] = "" - line["character_replacements"] = [] as Array[Dictionary] - line["text"] = l.replace("!ESCAPED_COLON!", ":") - - line["text_replacements"] = extract_dialogue_replacements(line.text, line.character.length() + 2 + indent_size) - for replacement in line.text_replacements: - if replacement.has("error"): - add_error(id, replacement.index, replacement.error) - - # Unescape any newlines - line["text"] = line.text.replace("\\n", "\n").strip_edges() - - # Work out where to go after this line - if line.next_id == DialogueConstants.ID_NULL: - line["next_id"] = get_line_after_line(id, indent_size, line) - - # Check for duplicate translation keys - if line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: - if line.has("translation_key"): - if known_translations.has(line.translation_key) and known_translations.get(line.translation_key) != line.text: - add_error(id, indent_size, DialogueConstants.ERR_DUPLICATE_ID) - else: - known_translations[line.translation_key] = line.text - else: - # Default translations key - if DialogueSettings.get_setting("missing_translations_are_errors", false): - add_error(id, indent_size, DialogueConstants.ERR_MISSING_ID) - else: - line["translation_key"] = line.text - - ## Error checking - - # Can't find goto - var jump_index: int = raw_line.find("=>") - match line.next_id: - DialogueConstants.ID_ERROR: - add_error(id, jump_index, DialogueConstants.ERR_UNKNOWN_TITLE) - DialogueConstants.ID_ERROR_INVALID_TITLE: - add_error(id, jump_index, DialogueConstants.ERR_INVALID_TITLE_REFERENCE) - DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY: - add_error(id, jump_index, DialogueConstants.ERR_TITLE_REFERENCE_HAS_NO_CONTENT) - - # Line after condition isn't indented once to the right - if line.type == DialogueConstants.TYPE_CONDITION: - if is_valid_id(line.next_id): - var next_line: String = raw_lines[line.next_id.to_int()] - var next_indent: int = get_indent(next_line) - if next_indent != indent_size + 1: - add_error(line.next_id.to_int(), next_indent, DialogueConstants.ERR_INVALID_INDENTATION) - else: - add_error(id, indent_size, DialogueConstants.ERR_INVALID_CONDITION_INDENTATION) - - # Line after normal line is indented to the right - elif line.type in [ - DialogueConstants.TYPE_TITLE, - DialogueConstants.TYPE_DIALOGUE, - DialogueConstants.TYPE_MUTATION, - DialogueConstants.TYPE_GOTO - ] and is_valid_id(line.next_id): - var next_line = raw_lines[line.next_id.to_int()] - if next_line != null and get_indent(next_line) > indent_size: - add_error(id, indent_size, DialogueConstants.ERR_INVALID_INDENTATION) - - # Parsing condition failed - if line.has("condition") and line.condition.has("error"): - add_error(id, line.condition.index, line.condition.error) - - # Parsing mutation failed - elif line.has("mutation") and line.mutation.has("error"): - add_error(id, line.mutation.index, line.mutation.error) - - # Line failed to parse at all - if line.get("type") == DialogueConstants.TYPE_UNKNOWN: - add_error(id, 0, DialogueConstants.ERR_UNKNOWN_LINE_SYNTAX) - - # If there are no titles then use the first actual line - if first_title == "" and not is_import_line(raw_line): - first_title = str(id) - - # If this line is the last line of a while loop, edit the id of its next line - if str(id) in while_loopbacks: - if is_goto_snippet_line(raw_line): - line["next_id_after"] = line["parent_id"] - elif is_condition_line(raw_line, true) or is_while_condition_line(raw_line): - line["next_conditional_id"] = line["parent_id"] - line["next_id_after"] = line["parent_id"] - elif is_goto_line(raw_line) or is_title_line(raw_line): - pass - else: - line["next_id"] = line["parent_id"] - - # Done! - parsed_lines[str(id)] = line - - # Assume the last line ends the dialogue - var last_line: Dictionary = parsed_lines.values()[parsed_lines.values().size() - 1] - if last_line.next_id == "": - last_line.next_id = DialogueConstants.ID_END - - if errors.size() > 0: - return ERR_PARSE_ERROR - - return OK - - -func get_data() -> DialogueManagerParseResult: - var data: DialogueManagerParseResult = DialogueManagerParseResult.new() - data.imported_paths = imported_paths - data.using_states = using_states - data.titles = titles - data.character_names = character_names - data.first_title = first_title - data.lines = parsed_lines - data.errors = errors - data.raw_text = raw_text - return data - - -## Get the last parse errors -func get_errors() -> Array[Dictionary]: - return errors - - -## Prepare the parser by collecting all lines and titles -func prepare(text: String, path: String, include_imported_titles_hashes: bool = true) -> void: - using_states = [] - errors = [] - imported_paths = [] - _imported_line_map = {} - while_loopbacks = [] - titles = {} - character_names = [] - first_title = "" - raw_lines = text.split("\n") - - # Work out imports - var known_imports: Dictionary = {} - - # Include the base file path so that we can get around circular dependencies - known_imports[path.hash()] = "." - - var imported_titles: Dictionary = {} - for id in range(0, raw_lines.size()): - var line = raw_lines[id] - if is_import_line(line): - var import_data = extract_import_path_and_name(line) - var import_hash: int = import_data.path.hash() - if import_data.size() > 0: - # Keep track of titles so we can add imported ones later - if str(import_hash) in imported_titles.keys(): - add_error(id, 0, DialogueConstants.ERR_FILE_ALREADY_IMPORTED) - if import_data.prefix in imported_titles.values(): - add_error(id, 0, DialogueConstants.ERR_DUPLICATE_IMPORT_NAME) - imported_titles[str(import_hash)] = import_data.prefix - - # Import the file content - if not known_imports.has(import_hash): - var error: Error = import_content(import_data.path, import_data.prefix, _imported_line_map, known_imports) - if error != OK: - add_error(id, 0, error) - - # Make a map so we can refer compiled lines to where they were imported from - if not _imported_line_map.has(import_hash): - _imported_line_map[import_hash] = { - hash = import_hash, - imported_on_line_number = id, - from_line = 0, - to_line = 0 - } - - var imported_content: String = "" - var cummulative_line_number: int = 0 - for item in _imported_line_map.values(): - item["from_line"] = cummulative_line_number - if known_imports.has(item.hash): - cummulative_line_number += known_imports[item.hash].split("\n").size() - item["to_line"] = cummulative_line_number - if known_imports.has(item.hash): - imported_content += known_imports[item.hash] + "\n" - - _imported_line_count = cummulative_line_number + 1 - - # Join it with the actual content - raw_lines = (imported_content + "\n" + text).split("\n") - - # Find all titles first - for id in range(0, raw_lines.size()): - if raw_lines[id].begins_with("~ "): - var title: String = extract_title(raw_lines[id]) - if title == "": - add_error(id, 2, DialogueConstants.ERR_EMPTY_TITLE) - elif titles.has(title): - add_error(id, 2, DialogueConstants.ERR_DUPLICATE_TITLE) - else: - var next_nonempty_line_id: String = get_next_nonempty_line_id(id) - if next_nonempty_line_id != DialogueConstants.ID_NULL: - titles[title] = next_nonempty_line_id - if "/" in title: - if include_imported_titles_hashes == false: - titles.erase(title) - var bits: PackedStringArray = title.split("/") - if imported_titles.has(bits[0]): - title = imported_titles[bits[0]] + "/" + bits[1] - titles[title] = next_nonempty_line_id - elif first_title == "": - first_title = next_nonempty_line_id - else: - titles[title] = DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY - - -func add_error(line_number: int, column_number: int, error: int) -> void: - # See if the error was in an imported file - for item in _imported_line_map.values(): - if line_number < item.to_line: - errors.append({ - line_number = item.imported_on_line_number, - column_number = 0, - error = DialogueConstants.ERR_ERRORS_IN_IMPORTED_FILE, - external_error = error, - external_line_number = line_number - }) - return - - # Otherwise, it's in this file - errors.append({ - line_number = line_number - _imported_line_count, - column_number = column_number, - error = error - }) - - -func remove_error(line_number: int, error: int) -> void: - for i in range(errors.size() - 1, -1, -1): - var err = errors[i] - var is_native_error = err.line_number == line_number - _imported_line_count and err.error == error - var is_external_error = err.get("external_line_number") == line_number and err.get("external_error") == error - if is_native_error or is_external_error: - errors.remove_at(i) - return - - -func is_import_line(line: String) -> bool: - return line.begins_with("import ") and " as " in line - - -func is_title_line(line: String) -> bool: - return line.strip_edges(true, false).begins_with("~ ") - - -func is_condition_line(line: String, include_else: bool = true) -> bool: - line = line.strip_edges(true, false) - if line.begins_with("if ") or line.begins_with("elif ") or line.begins_with("else if"): return true - if include_else and line.begins_with("else"): return true - return false - -func is_while_condition_line(line: String) -> bool: - line = line.strip_edges(true, false) - if line.begins_with("while "): return true - return false - - -func is_mutation_line(line: String) -> bool: - line = line.strip_edges(true, false) - return line.begins_with("do ") or line.begins_with("do! ") or line.begins_with("set ") - - -func is_goto_line(line: String) -> bool: - line = line.strip_edges(true, false) - line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(line, "") - return line.begins_with("=> ") or line.begins_with("=>< ") - - -func is_goto_snippet_line(line: String) -> bool: - line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(line.strip_edges(), "") - return line.begins_with("=>< ") - - -func is_nested_dialogue_line(raw_line: String, parsed_lines: Dictionary, raw_lines: PackedStringArray, indent_size: int) -> bool: - if parsed_lines.values().is_empty(): return false - if raw_line.strip_edges().begins_with("#"): return false - - var parent_line: Dictionary = parsed_lines.values().back() - if parent_line.type != DialogueConstants.TYPE_DIALOGUE: return false - if get_indent(raw_lines[parent_line.id.to_int()]) >= indent_size: return false - return true - - -func is_dialogue_line(line: String) -> bool: - if line == null: return false - if is_response_line(line): return false - if is_title_line(line): return false - if is_condition_line(line, true): return false - if is_mutation_line(line): return false - if is_goto_line(line): return false - return true - - -func is_response_line(line: String) -> bool: - return line.strip_edges(true, false).begins_with("- ") - - -func is_valid_id(id: String) -> bool: - return false if id in [DialogueConstants.ID_NULL, DialogueConstants.ID_ERROR, DialogueConstants.ID_END_CONVERSATION] else true - - -func is_line_empty(line: String) -> bool: - line = line.strip_edges() - - if line == "": return true - if line == "endif": return true - if line.begins_with("#"): return true - - return false - - -func get_line_after_line(id: int, indent_size: int, line: Dictionary) -> String: - # Unless the next line is an outdent we can assume it comes next - var next_nonempty_line_id = get_next_nonempty_line_id(id) - if next_nonempty_line_id != DialogueConstants.ID_NULL \ - and indent_size <= get_indent(raw_lines[next_nonempty_line_id.to_int()]): - # The next line is a title so we need the next nonempty line after that - if is_title_line(raw_lines[next_nonempty_line_id.to_int()]): - return get_next_nonempty_line_id(next_nonempty_line_id.to_int()) - # Otherwise it's a normal line - else: - return next_nonempty_line_id - # Otherwise, we grab the ID from the parents next ID after children - elif line.has("parent_id") and parsed_lines.has(line.parent_id): - return parsed_lines[line.parent_id].next_id_after - - else: - return DialogueConstants.ID_NULL - - -func get_indent(line: String) -> int: - var tabs: RegExMatch = INDENT_REGEX.search(line) - if tabs: - return tabs.get_string().length() - else: - return 0 - - -func get_next_nonempty_line_id(line_number: int) -> String: - for i in range(line_number + 1, raw_lines.size()): - if not is_line_empty(raw_lines[i]): - return str(i) - return DialogueConstants.ID_NULL - - -func find_previous_response_id(line_number: int) -> String: - var line = raw_lines[line_number] - var indent_size = get_indent(line) - - # Look back up the list to find the previous response - var last_found_response_id: String = str(line_number) - - for i in range(line_number - 1, -1, -1): - line = raw_lines[i] - - if is_line_empty(line): continue - - # If its a response at the same indent level then its a match - elif get_indent(line) == indent_size: - if line.strip_edges().begins_with("- "): - last_found_response_id = str(i) - else: - return last_found_response_id - - # Return itself if nothing was found - return last_found_response_id - - -func apply_weighted_random(id: int, raw_line: String, indent_size: int, line: Dictionary) -> void: - var weight: float = 1 - var found = WEIGHTED_RANDOM_SIBLINGS_REGEX.search(raw_line) - if found and found.names.has("weight"): - weight = found.strings[found.names.weight].to_float() - - # Look back up the list to find the first weighted random line in this group - var original_random_line: Dictionary = {} - for i in range(id, 0, -1): - # Ignore doc comment lines - if raw_lines[i].strip_edges().begins_with("##"): - continue - # Lines that aren't prefixed with the random token are a dead end - if not raw_lines[i].strip_edges().begins_with("%") or get_indent(raw_lines[i]) != indent_size: - break - # Make sure we group random dialogue and random lines separately - elif WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_line.strip_edges(), "").begins_with("=") != WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_lines[i].strip_edges(), "").begins_with("="): - break - # Otherwise we've found the origin - elif parsed_lines.has(str(i)) and parsed_lines[str(i)].has("siblings"): - original_random_line = parsed_lines[str(i)] - break - - # Attach it to the original random line and work out where to go after the line - if original_random_line.size() > 0: - original_random_line["siblings"] += [{ weight = weight, id = str(id) }] - if original_random_line.type != DialogueConstants.TYPE_GOTO: - # Update the next line for all siblings (not goto lines, though, they manager their - # own next ID) - original_random_line["next_id"] = get_line_after_line(id, indent_size, line) - for sibling in original_random_line["siblings"]: - if sibling.id in parsed_lines: - parsed_lines[sibling.id]["next_id"] = original_random_line["next_id"] - line["next_id"] = original_random_line.next_id - # Or set up this line as the original - else: - line["siblings"] = [{ weight = weight, id = str(id) }] - line["next_id"] = get_line_after_line(id, indent_size, line) - - if line.next_id == DialogueConstants.ID_NULL: - line["next_id"] = DialogueConstants.ID_END - - -func find_next_condition_sibling(line_number: int) -> String: - var line = raw_lines[line_number] - var expected_indent = get_indent(line) - - # Look down the list and find an elif or else at the same indent level - for i in range(line_number + 1, raw_lines.size()): - line = raw_lines[i] - if is_line_empty(line): continue - - var l = line.strip_edges() - if l.begins_with("~ "): - return DialogueConstants.ID_END_CONVERSATION - - elif get_indent(line) < expected_indent: - return DialogueConstants.ID_NULL - - elif get_indent(line) == expected_indent: - # Found an if, which begins a different block - if l.begins_with("if"): - return DialogueConstants.ID_NULL - - # Found what we're looking for - elif (l.begins_with("elif ") or l.begins_with("else")): - return str(i) - - return DialogueConstants.ID_NULL - - -func find_next_line_after_conditions(line_number: int) -> String: - var line = raw_lines[line_number] - var expected_indent = get_indent(line) - - # Look down the list for the first non condition line at the same or less indent level - for i in range(line_number + 1, raw_lines.size()): - line = raw_lines[i] - - if is_line_empty(line): continue - - var line_indent = get_indent(line) - line = line.strip_edges() - - if is_title_line(line): - return get_next_nonempty_line_id(i) - - elif line_indent > expected_indent: - continue - - elif line_indent == expected_indent: - if line.begins_with("elif ") or line.begins_with("else"): - continue - else: - return str(i) - - elif line_indent < expected_indent: - # We have to check the parent of this block - for p in range(line_number - 1, -1, -1): - line = raw_lines[p] - - if is_line_empty(line): continue - - line_indent = get_indent(line) - if line_indent < expected_indent: - return parsed_lines[str(p)].get("next_id_after", DialogueConstants.ID_NULL) - - return DialogueConstants.ID_END_CONVERSATION - -func find_last_line_within_conditions(line_number: int) -> String: - var line = raw_lines[line_number] - var expected_indent = get_indent(line) - - var candidate = DialogueConstants.ID_NULL - - # Look down the list for the last line that has an indent level 1 more than this line - # Ending the search when you find a line the same or less indent level - for i in range(line_number + 1, raw_lines.size()): - line = raw_lines[i] - - if is_line_empty(line): continue - - var line_indent = get_indent(line) - line = line.strip_edges() - - if line_indent > expected_indent + 1: - continue - elif line_indent == (expected_indent + 1): - candidate = i - else: - break - - return str(candidate) - -func find_next_line_after_responses(line_number: int) -> String: - var line = raw_lines[line_number] - var expected_indent = get_indent(line) - - # Find the first line after this one that has a smaller indent that isn't another option - # If we hit the eof then we give up - for i in range(line_number + 1, raw_lines.size()): - line = raw_lines[i] - - if is_line_empty(line): continue - - var indent = get_indent(line) - - line = line.strip_edges() - - # We hit a title so the next line is a new start - if is_title_line(line): - return get_next_nonempty_line_id(i) - - # Another option - elif line.begins_with("- "): - if indent == expected_indent: - # ...at the same level so we continue - continue - elif indent < expected_indent: - # ...outdented so check the previous parent - var previous_parent = parent_stack[parent_stack.size() - 2] - if parsed_lines.has(str(previous_parent)): - return parsed_lines[str(previous_parent)].next_id_after - else: - return DialogueConstants.ID_NULL - - # We're at the end of a conditional so jump back up to see what's after it - elif line.begins_with("elif ") or line.begins_with("else"): - for p in range(line_number - 1, -1, -1): - line = raw_lines[p] - - if is_line_empty(line): continue - - var line_indent = get_indent(line) - if line_indent < expected_indent: - return parsed_lines[str(p)].next_id_after - - # Otherwise check the indent for an outdent - else: - line_number = i - line = raw_lines[line_number] - if get_indent(line) <= expected_indent: - return str(line_number) - - # EOF so must be end of conversation - return DialogueConstants.ID_END_CONVERSATION - - -## Get the names of any autoloads in the project -func get_autoload_names() -> PackedStringArray: - var autoloads: PackedStringArray = [] - - var project = ConfigFile.new() - project.load("res://project.godot") - if project.has_section("autoload"): - return Array(project.get_section_keys("autoload")).filter(func(key): return key != "DialogueManager") - - return autoloads - - -## Import content from another dialogue file or return an ERR -func import_content(path: String, prefix: String, imported_line_map: Dictionary, known_imports: Dictionary) -> Error: - if FileAccess.file_exists(path): - var file = FileAccess.open(path, FileAccess.READ) - var content: PackedStringArray = file.get_as_text().split("\n") - - var imported_titles: Dictionary = {} - - for index in range(0, content.size()): - var line = content[index] - if is_import_line(line): - var import = extract_import_path_and_name(line) - if import.size() > 0: - if not known_imports.has(import.path.hash()): - # Add an empty record into the keys just so we don't end up with cyclic dependencies - known_imports[import.path.hash()] = "" - if import_content(import.path, import.prefix, imported_line_map, known_imports) != OK: - return ERR_LINK_FAILED - - if not imported_line_map.has(import.path.hash()): - # Make a map so we can refer compiled lines to where they were imported from - imported_line_map[import.path.hash()] = { - hash = import.path.hash(), - imported_on_line_number = index, - from_line = 0, - to_line = 0 - } - - imported_titles[import.prefix] = import.path.hash() - - var origin_hash: int = -1 - for hash_value in known_imports.keys(): - if known_imports[hash_value] == ".": - origin_hash = hash_value - - # Replace any titles or jump points with references to the files they point to (event if they point to their own file) - for i in range(0, content.size()): - var line = content[i] - if is_title_line(line): - var title = extract_title(line) - if "/" in line: - var bits = title.split("/") - content[i] = "~ %s/%s" % [imported_titles[bits[0]], bits[1]] - else: - content[i] = "~ %s/%s" % [str(path.hash()), title] - - elif "=>< " in line: - var jump: String = line.substr(line.find("=>< ") + "=>< ".length()).strip_edges() - if "/" in jump: - var bits: PackedStringArray = jump.split("/") - var title_hash: int = imported_titles[bits[0]] - if title_hash == origin_hash: - content[i] = "%s=>< %s" % [line.split("=>< ")[0], bits[1]] - else: - content[i] = "%s=>< %s/%s" % [line.split("=>< ")[0], title_hash, bits[1]] - - elif not jump in ["END", "END!"]: - content[i] = "%s=>< %s/%s" % [line.split("=>< ")[0], str(path.hash()), jump] - - elif "=> " in line: - var jump: String = line.substr(line.find("=> ") + "=> ".length()).strip_edges() - if "/" in jump: - var bits: PackedStringArray = jump.split("/") - var title_hash: int = imported_titles[bits[0]] - if title_hash == origin_hash: - content[i] = "%s=> %s" % [line.split("=> ")[0], bits[1]] - else: - content[i] = "%s=> %s/%s" % [line.split("=> ")[0], title_hash, bits[1]] - - elif not jump in ["END", "END!"]: - content[i] = "%s=> %s/%s" % [line.split("=> ")[0], str(path.hash()), jump] - - imported_paths.append(path) - known_imports[path.hash()] = "\n".join(content) + "\n=> END\n" - return OK - else: - return ERR_FILE_NOT_FOUND - - -func extract_import_path_and_name(line: String) -> Dictionary: - var found: RegExMatch = IMPORT_REGEX.search(line) - if found: - return { - path = found.strings[found.names.path], - prefix = found.strings[found.names.prefix] - } - else: - return {} - - -func extract_title(line: String) -> String: - return line.substr(2).strip_edges() - - -func extract_translation(line: String) -> String: - # Find a static translation key, eg. [ID:something] - var found: RegExMatch = TRANSLATION_REGEX.search(line) - if found: - return found.strings[found.names.tr] - else: - return "" - - -func extract_response_prompt(line: String) -> String: - # Find just the text prompt from a response, ignoring any conditions or gotos - line = line.substr(2) - if " [if " in line: - line = line.substr(0, line.find(" [if ")) - if " =>" in line: - line = line.substr(0, line.find(" =>")) - - # Without the translation key if there is one - var translation_key: String = extract_translation(line) - if translation_key: - line = line.replace("[ID:%s]" % translation_key, "") - - return line.replace("\\n", "\n").strip_edges() - - -func parse_response_character_and_text(id: int, text: String, line: Dictionary, indent_size: int, parsed_lines: Dictionary) -> void: - var bits = Array(text.strip_edges().split(": ")) - line["character"] = bits.pop_front().strip_edges() - line["character_replacements"] = extract_dialogue_replacements(line.character, line.character.length() + 2 + indent_size) - for replacement in line.character_replacements: - if replacement.has("error"): - add_error(id, replacement.index, replacement.error) - - if not line["character"] in character_names: - character_names.append(line["character"]) - - line["text"] = ": ".join(bits).replace("!ESCAPED_COLON!", ":").strip_edges() - - if line.get("translation_key", null) == null: - line["translation_key"] = line.text - - -func extract_mutation(line: String) -> Dictionary: - var found: RegExMatch = MUTATION_REGEX.search(line) - - if not found: - return { - index = 0, - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - - if found.names.has("mutation"): - var expression: Array = tokenise(found.strings[found.names.mutation], DialogueConstants.TYPE_MUTATION, found.get_start("mutation")) - if expression.size() == 0: - return { - index = found.get_start("mutation"), - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - elif expression[0].type == DialogueConstants.TYPE_ERROR: - return { - index = expression[0].index, - error = expression[0].value - } - else: - return { - expression = expression, - is_blocking = not "!" in found.strings[found.names.keyword] - } - - else: - return { - index = found.get_start(), - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - - -func extract_condition(raw_line: String, is_wrapped: bool, index: int) -> Dictionary: - var condition: Dictionary = {} - - var regex: RegEx = WRAPPED_CONDITION_REGEX if is_wrapped else CONDITION_REGEX - var found: RegExMatch = regex.search(raw_line) - - if found == null: - return { - index = 0, - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - - var raw_condition: String = found.strings[found.names.condition] - var expression: Array = tokenise(raw_condition, DialogueConstants.TYPE_CONDITION, index + found.get_start("condition")) - - if expression.size() == 0: - return { - index = index + found.get_start("condition"), - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - elif expression[0].type == DialogueConstants.TYPE_ERROR: - return { - index = expression[0].index, - error = expression[0].value - } - else: - return { - expression = expression - } - - -func extract_dialogue_replacements(text: String, index: int) -> Array[Dictionary]: - var founds: Array[RegExMatch] = REPLACEMENTS_REGEX.search_all(text) - - if founds == null or founds.size() == 0: - return [] - - var replacements: Array[Dictionary] = [] - for found in founds: - var replacement: Dictionary = {} - var value_in_text: String = found.strings[1] - var expression: Array = tokenise(value_in_text, DialogueConstants.TYPE_DIALOGUE, index + found.get_start(1)) - if expression.size() == 0: - replacement = { - index = index + found.get_start(1), - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - elif expression[0].type == DialogueConstants.TYPE_ERROR: - replacement = { - index = expression[0].index, - error = expression[0].value - } - else: - replacement = { - value_in_text = "{{%s}}" % value_in_text, - expression = expression - } - replacements.append(replacement) - - return replacements - - -func extract_goto(line: String) -> String: - var found: RegExMatch = GOTO_REGEX.search(line) - - if found == null: return DialogueConstants.ID_ERROR - - var title: String = found.strings[found.names.jump_to_title].strip_edges() - - if " " in title or title == "": - return DialogueConstants.ID_ERROR_INVALID_TITLE - - # "=> END!" means end the conversation - if title == "END!": - return DialogueConstants.ID_END_CONVERSATION - # "=> END" means end the current title (and go back to the previous one if there is one - # in the stack) - elif title == "END": - return DialogueConstants.ID_END - - elif titles.has(title): - return titles.get(title) - else: - return DialogueConstants.ID_ERROR - - -func extract_tags(line: String) -> ResolvedTagData: - var resolved_tags: PackedStringArray = [] - var tag_matches: Array[RegExMatch] = TAGS_REGEX.search_all(line) - for tag_match in tag_matches: - line = line.replace(tag_match.get_string(), "") - var tags = tag_match.get_string().replace("[#", "").replace("]", "").replace(", ", ",").split(",") - for tag in tags: - tag = tag.replace("#", "") - if not tag in resolved_tags: - resolved_tags.append(tag) - - return ResolvedTagData.new({ - tags = resolved_tags, - line_without_tags = line - }) - - -func extract_markers(line: String) -> ResolvedLineData: - var text: String = line - var pauses: Dictionary = {} - var speeds: Dictionary = {} - var mutations: Array[Array] = [] - var bbcodes: Array = [] - var time: String = "" - - # Remove any escaped brackets (ie. "\[") - var escaped_open_brackets: PackedInt32Array = [] - var escaped_close_brackets: PackedInt32Array = [] - for i in range(0, text.length() - 1): - if text.substr(i, 2) == "\\[": - text = text.substr(0, i) + "!" + text.substr(i + 2) - escaped_open_brackets.append(i) - elif text.substr(i, 2) == "\\]": - text = text.substr(0, i) + "!" + text.substr(i + 2) - escaped_close_brackets.append(i) - - # Extract all of the BB codes so that we know the actual text (we could do this easier with - # a RichTextLabel but then we'd need to await idle_frame which is annoying) - var bbcode_positions = find_bbcode_positions_in_string(text) - var accumulaive_length_offset = 0 - for position in bbcode_positions: - # Ignore our own markers - if position.code in ["wait", "speed", "/speed", "do", "do!", "set", "next", "if", "else", "/if"]: - continue - - bbcodes.append({ - bbcode = position.bbcode, - start = position.start, - offset_start = position.start - accumulaive_length_offset - }) - accumulaive_length_offset += position.bbcode.length() - - for bb in bbcodes: - text = text.substr(0, bb.offset_start) + text.substr(bb.offset_start + bb.bbcode.length()) - - # Now find any dialogue markers - var next_bbcode_position = find_bbcode_positions_in_string(text, false) - var limit = 0 - while next_bbcode_position.size() > 0 and limit < 1000: - limit += 1 - - var bbcode = next_bbcode_position[0] - - var index = bbcode.start - var code = bbcode.code - var raw_args = bbcode.raw_args - var args = {} - if code in ["do", "do!", "set"]: - args["value"] = extract_mutation("%s %s" % [code, raw_args]) - else: - # Could be something like: - # "=1.0" - # " rate=20 level=10" - if raw_args and raw_args[0] == "=": - raw_args = "value" + raw_args - for pair in raw_args.strip_edges().split(" "): - if "=" in pair: - var bits = pair.split("=") - args[bits[0]] = bits[1] - - match code: - "wait": - if pauses.has(index): - pauses[index] += args.get("value").to_float() - else: - pauses[index] = args.get("value").to_float() - "speed": - speeds[index] = args.get("value").to_float() - "/speed": - speeds[index] = 1.0 - "do", "do!", "set": - mutations.append([index, args.get("value")]) - "next": - time = args.get("value") if args.has("value") else "0" - - # Find any BB codes that are after this index and remove the length from their start - var length = bbcode.bbcode.length() - for bb in bbcodes: - if bb.offset_start > bbcode.start: - bb.offset_start -= length - bb.start -= length - - # Find any escaped brackets after this that need moving - for i in range(0, escaped_open_brackets.size()): - if escaped_open_brackets[i] > bbcode.start: - escaped_open_brackets[i] -= length - for i in range(0, escaped_close_brackets.size()): - if escaped_close_brackets[i] > bbcode.start: - escaped_close_brackets[i] -= length - - text = text.substr(0, index) + text.substr(index + length) - next_bbcode_position = find_bbcode_positions_in_string(text, false) - - # Put the BB Codes back in - for bb in bbcodes: - text = text.insert(bb.start, bb.bbcode) - - # Put the escaped brackets back in - for index in escaped_open_brackets: - text = text.left(index) + "[" + text.right(text.length() - index - 1) - for index in escaped_close_brackets: - text = text.left(index) + "]" + text.right(text.length() - index - 1) - - return ResolvedLineData.new({ - text = text, - pauses = pauses, - speeds = speeds, - mutations = mutations, - time = time - }) - - -func find_bbcode_positions_in_string(string: String, find_all: bool = true) -> Array[Dictionary]: - if not "[" in string: return [] - - var positions: Array[Dictionary] = [] - - var open_brace_count: int = 0 - var start: int = 0 - var bbcode: String = "" - var code: String = "" - var is_finished_code: bool = false - for i in range(0, string.length()): - if string[i] == "[": - if open_brace_count == 0: - start = i - bbcode = "" - code = "" - is_finished_code = false - open_brace_count += 1 - - else: - if not is_finished_code and (string[i].to_upper() != string[i] or string[i] == "/" or string[i] == "!"): - code += string[i] - else: - is_finished_code = true - - if open_brace_count > 0: - bbcode += string[i] - - if string[i] == "]": - open_brace_count -= 1 - if open_brace_count == 0 and not code in ["if", "else", "/if"]: - positions.append({ - bbcode = bbcode, - code = code, - start = start, - raw_args = bbcode.substr(code.length() + 1, bbcode.length() - code.length() - 2).strip_edges() - }) - - if not find_all: - return positions - - return positions - - -func tokenise(text: String, line_type: String, index: int) -> Array: - var tokens: Array[Dictionary] = [] - var limit: int = 0 - while text.strip_edges() != "" and limit < 1000: - limit += 1 - var found = find_match(text) - if found.size() > 0: - tokens.append({ - index = index, - type = found.type, - value = found.value - }) - index += found.value.length() - text = found.remaining_text - elif text.begins_with(" "): - index += 1 - text = text.substr(1) - else: - return build_token_tree_error(DialogueConstants.ERR_INVALID_EXPRESSION, index) - - return build_token_tree(tokens, line_type, "")[0] - - -func build_token_tree_error(error: int, index: int) -> Array: - return [{ type = DialogueConstants.TOKEN_ERROR, value = error, index = index }] - - -func build_token_tree(tokens: Array[Dictionary], line_type: String, expected_close_token: String) -> Array: - var tree: Array[Dictionary] = [] - var limit = 0 - while tokens.size() > 0 and limit < 1000: - limit += 1 - var token = tokens.pop_front() - - var error = check_next_token(token, tokens, line_type, expected_close_token) - if error != OK: - return [build_token_tree_error(error, token.index), tokens] - - match token.type: - DialogueConstants.TOKEN_FUNCTION: - var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_PARENS_CLOSE) - - if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: - return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] - - tree.append({ - type = DialogueConstants.TOKEN_FUNCTION, - # Consume the trailing "(" - function = token.value.substr(0, token.value.length() - 1), - value = tokens_to_list(sub_tree[0]) - }) - tokens = sub_tree[1] - - DialogueConstants.TOKEN_DICTIONARY_REFERENCE: - var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACKET_CLOSE) - - if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: - return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] - - var args = tokens_to_list(sub_tree[0]) - if args.size() != 1: - return [build_token_tree_error(DialogueConstants.ERR_INVALID_INDEX, token.index), tokens] - - tree.append({ - type = DialogueConstants.TOKEN_DICTIONARY_REFERENCE, - # Consume the trailing "[" - variable = token.value.substr(0, token.value.length() - 1), - value = args[0] - }) - tokens = sub_tree[1] - - DialogueConstants.TOKEN_BRACE_OPEN: - var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACE_CLOSE) - - if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: - return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] - - var t = sub_tree[0] - for i in range(0, t.size() - 2): - # Convert Lua style dictionaries to string keys - if t[i].type == DialogueConstants.TOKEN_VARIABLE and t[i+1].type == DialogueConstants.TOKEN_ASSIGNMENT: - t[i].type = DialogueConstants.TOKEN_STRING - t[i+1].type = DialogueConstants.TOKEN_COLON - t[i+1].erase("value") - - tree.append({ - type = DialogueConstants.TOKEN_DICTIONARY, - value = tokens_to_dictionary(sub_tree[0]) - }) - - tokens = sub_tree[1] - - DialogueConstants.TOKEN_BRACKET_OPEN: - var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACKET_CLOSE) - - if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: - return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] - - var type = DialogueConstants.TOKEN_ARRAY - var value = tokens_to_list(sub_tree[0]) - - # See if this is referencing a nested dictionary value - if tree.size() > 0: - var previous_token = tree[tree.size() - 1] - if previous_token.type in [DialogueConstants.TOKEN_DICTIONARY_REFERENCE, DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE]: - type = DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE - value = value[0] - - tree.append({ - type = type, - value = value - }) - tokens = sub_tree[1] - - DialogueConstants.TOKEN_PARENS_OPEN: - var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_PARENS_CLOSE) - - if sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: - return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] - - tree.append({ - type = DialogueConstants.TOKEN_GROUP, - value = sub_tree[0] - }) - tokens = sub_tree[1] - - DialogueConstants.TOKEN_PARENS_CLOSE, \ - DialogueConstants.TOKEN_BRACE_CLOSE, \ - DialogueConstants.TOKEN_BRACKET_CLOSE: - if token.type != expected_close_token: - return [build_token_tree_error(DialogueConstants.ERR_UNEXPECTED_CLOSING_BRACKET, token.index), tokens] - - return [tree, tokens] - - DialogueConstants.TOKEN_NOT: - # Double nots negate each other - if tokens.size() > 0 and tokens.front().type == DialogueConstants.TOKEN_NOT: - tokens.pop_front() - else: - tree.append({ - type = token.type - }) - - DialogueConstants.TOKEN_COMMA, \ - DialogueConstants.TOKEN_COLON, \ - DialogueConstants.TOKEN_DOT: - tree.append({ - type = token.type - }) - - DialogueConstants.TOKEN_COMPARISON, \ - DialogueConstants.TOKEN_ASSIGNMENT, \ - DialogueConstants.TOKEN_OPERATOR, \ - DialogueConstants.TOKEN_AND_OR, \ - DialogueConstants.TOKEN_VARIABLE: \ - tree.append({ - type = token.type, - value = token.value.strip_edges() - }) - - DialogueConstants.TOKEN_STRING: - tree.append({ - type = token.type, - value = token.value.substr(1, token.value.length() - 2) - }) - - DialogueConstants.TOKEN_CONDITION: - return [build_token_tree_error(DialogueConstants.ERR_UNEXPECTED_CONDITION, token.index), token] - - DialogueConstants.TOKEN_BOOL: - tree.append({ - type = token.type, - value = token.value.to_lower() == "true" - }) - - DialogueConstants.TOKEN_NUMBER: - var value = token.value.to_float() if "." in token.value else token.value.to_int() - # If previous token is a number and this one is a negative number then - # inject a minus operator token in between them. - if tree.size() > 0 and token.value.begins_with("-") and tree[tree.size() - 1].type == DialogueConstants.TOKEN_NUMBER: - tree.append(({ - type = DialogueConstants.TOKEN_OPERATOR, - value = "-" - })) - tree.append({ - type = token.type, - value = -1 * value - }) - else: - tree.append({ - type = token.type, - value = value - }) - - if expected_close_token != "": - var index: int = tokens[0].index if tokens.size() > 0 else 0 - return [build_token_tree_error(DialogueConstants.ERR_MISSING_CLOSING_BRACKET, index), tokens] - - return [tree, tokens] - - -func check_next_token(token: Dictionary, next_tokens: Array[Dictionary], line_type: String, expected_close_token: String) -> Error: - var next_token: Dictionary = { type = null } - if next_tokens.size() > 0: - next_token = next_tokens.front() - - # Guard for assigning in a condition. If the assignment token isn't inside a Lua dictionary - # then it's an unexpected assignment in a condition line. - if token.type == DialogueConstants.TOKEN_ASSIGNMENT and line_type == DialogueConstants.TYPE_CONDITION and not next_tokens.any(func(t): return t.type == expected_close_token): - return DialogueConstants.ERR_UNEXPECTED_ASSIGNMENT - - # Special case for a negative number after this one - if token.type == DialogueConstants.TOKEN_NUMBER and next_token.type == DialogueConstants.TOKEN_NUMBER and next_token.value.begins_with("-"): - return OK - - var expected_token_types = [] - var unexpected_token_types = [] - match token.type: - DialogueConstants.TOKEN_FUNCTION, \ - DialogueConstants.TOKEN_PARENS_OPEN: - unexpected_token_types = [ - null, - DialogueConstants.TOKEN_COMMA, - DialogueConstants.TOKEN_COLON, - DialogueConstants.TOKEN_COMPARISON, - DialogueConstants.TOKEN_ASSIGNMENT, - DialogueConstants.TOKEN_OPERATOR, - DialogueConstants.TOKEN_AND_OR, - DialogueConstants.TOKEN_DOT - ] - - DialogueConstants.TOKEN_BRACKET_CLOSE: - unexpected_token_types = [ - DialogueConstants.TOKEN_NOT, - DialogueConstants.TOKEN_BOOL, - DialogueConstants.TOKEN_STRING, - DialogueConstants.TOKEN_NUMBER, - DialogueConstants.TOKEN_VARIABLE - ] - - DialogueConstants.TOKEN_BRACE_OPEN: - expected_token_types = [ - DialogueConstants.TOKEN_STRING, - DialogueConstants.TOKEN_VARIABLE, - DialogueConstants.TOKEN_NUMBER, - DialogueConstants.TOKEN_BRACE_CLOSE - ] - - DialogueConstants.TOKEN_PARENS_CLOSE, \ - DialogueConstants.TOKEN_BRACE_CLOSE: - unexpected_token_types = [ - DialogueConstants.TOKEN_NOT, - DialogueConstants.TOKEN_ASSIGNMENT, - DialogueConstants.TOKEN_BOOL, - DialogueConstants.TOKEN_STRING, - DialogueConstants.TOKEN_NUMBER, - DialogueConstants.TOKEN_VARIABLE - ] - - DialogueConstants.TOKEN_COMPARISON, \ - DialogueConstants.TOKEN_OPERATOR, \ - DialogueConstants.TOKEN_COMMA, \ - DialogueConstants.TOKEN_DOT, \ - DialogueConstants.TOKEN_NOT, \ - DialogueConstants.TOKEN_AND_OR, \ - DialogueConstants.TOKEN_DICTIONARY_REFERENCE: - unexpected_token_types = [ - null, - DialogueConstants.TOKEN_COMMA, - DialogueConstants.TOKEN_COLON, - DialogueConstants.TOKEN_COMPARISON, - DialogueConstants.TOKEN_ASSIGNMENT, - DialogueConstants.TOKEN_OPERATOR, - DialogueConstants.TOKEN_AND_OR, - DialogueConstants.TOKEN_PARENS_CLOSE, - DialogueConstants.TOKEN_BRACE_CLOSE, - DialogueConstants.TOKEN_BRACKET_CLOSE, - DialogueConstants.TOKEN_DOT - ] - - DialogueConstants.TOKEN_COLON: - unexpected_token_types = [ - DialogueConstants.TOKEN_COMMA, - DialogueConstants.TOKEN_COLON, - DialogueConstants.TOKEN_COMPARISON, - DialogueConstants.TOKEN_ASSIGNMENT, - DialogueConstants.TOKEN_OPERATOR, - DialogueConstants.TOKEN_AND_OR, - DialogueConstants.TOKEN_PARENS_CLOSE, - DialogueConstants.TOKEN_BRACE_CLOSE, - DialogueConstants.TOKEN_BRACKET_CLOSE, - DialogueConstants.TOKEN_DOT - ] - - DialogueConstants.TOKEN_BOOL, \ - DialogueConstants.TOKEN_STRING, \ - DialogueConstants.TOKEN_NUMBER: - unexpected_token_types = [ - DialogueConstants.TOKEN_NOT, - DialogueConstants.TOKEN_ASSIGNMENT, - DialogueConstants.TOKEN_BOOL, - DialogueConstants.TOKEN_STRING, - DialogueConstants.TOKEN_NUMBER, - DialogueConstants.TOKEN_VARIABLE, - DialogueConstants.TOKEN_FUNCTION, - DialogueConstants.TOKEN_PARENS_OPEN, - DialogueConstants.TOKEN_BRACE_OPEN, - DialogueConstants.TOKEN_BRACKET_OPEN - ] - - DialogueConstants.TOKEN_VARIABLE: - unexpected_token_types = [ - DialogueConstants.TOKEN_NOT, - DialogueConstants.TOKEN_BOOL, - DialogueConstants.TOKEN_STRING, - DialogueConstants.TOKEN_NUMBER, - DialogueConstants.TOKEN_VARIABLE, - DialogueConstants.TOKEN_FUNCTION, - DialogueConstants.TOKEN_PARENS_OPEN, - DialogueConstants.TOKEN_BRACE_OPEN, - DialogueConstants.TOKEN_BRACKET_OPEN - ] - - if (expected_token_types.size() > 0 and not next_token.type in expected_token_types or unexpected_token_types.size() > 0 and next_token.type in unexpected_token_types): - match next_token.type: - null: - return DialogueConstants.ERR_UNEXPECTED_END_OF_EXPRESSION - - DialogueConstants.TOKEN_FUNCTION: - return DialogueConstants.ERR_UNEXPECTED_FUNCTION - - DialogueConstants.TOKEN_PARENS_OPEN, \ - DialogueConstants.TOKEN_PARENS_CLOSE: - return DialogueConstants.ERR_UNEXPECTED_BRACKET - - DialogueConstants.TOKEN_COMPARISON, \ - DialogueConstants.TOKEN_ASSIGNMENT, \ - DialogueConstants.TOKEN_OPERATOR, \ - DialogueConstants.TOKEN_NOT, \ - DialogueConstants.TOKEN_AND_OR: - return DialogueConstants.ERR_UNEXPECTED_OPERATOR - - DialogueConstants.TOKEN_COMMA: - return DialogueConstants.ERR_UNEXPECTED_COMMA - DialogueConstants.TOKEN_COLON: - return DialogueConstants.ERR_UNEXPECTED_COLON - DialogueConstants.TOKEN_DOT: - return DialogueConstants.ERR_UNEXPECTED_DOT - - DialogueConstants.TOKEN_BOOL: - return DialogueConstants.ERR_UNEXPECTED_BOOLEAN - DialogueConstants.TOKEN_STRING: - return DialogueConstants.ERR_UNEXPECTED_STRING - DialogueConstants.TOKEN_NUMBER: - return DialogueConstants.ERR_UNEXPECTED_NUMBER - DialogueConstants.TOKEN_VARIABLE: - return DialogueConstants.ERR_UNEXPECTED_VARIABLE - - return DialogueConstants.ERR_INVALID_EXPRESSION - - return OK - - -func tokens_to_list(tokens: Array[Dictionary]) -> Array[Array]: - var list: Array[Array] = [] - var current_item: Array[Dictionary] = [] - for token in tokens: - if token.type == DialogueConstants.TOKEN_COMMA: - list.append(current_item) - current_item = [] - else: - current_item.append(token) - - if current_item.size() > 0: - list.append(current_item) - - return list - - -func tokens_to_dictionary(tokens: Array[Dictionary]) -> Dictionary: - var dictionary = {} - for i in range(0, tokens.size()): - if tokens[i].type == DialogueConstants.TOKEN_COLON: - if tokens.size() == i + 2: - dictionary[tokens[i-1]] = tokens[i+1] - else: - dictionary[tokens[i-1]] = { type = DialogueConstants.TOKEN_GROUP, value = tokens.slice(i+1) } - - return dictionary - - -func find_match(input: String) -> Dictionary: - for key in TOKEN_DEFINITIONS.keys(): - var regex = TOKEN_DEFINITIONS.get(key) - var found = regex.search(input) - if found: - return { - type = key, - remaining_text = input.substr(found.strings[0].length()), - value = found.strings[0] - } - - return {} diff --git a/addons/dialogue_manager/components/resolved_line_data.gd b/addons/dialogue_manager/components/resolved_line_data.gd deleted file mode 100644 index 1073586..0000000 --- a/addons/dialogue_manager/components/resolved_line_data.gd +++ /dev/null @@ -1,15 +0,0 @@ -extends RefCounted - -var text: String = "" -var pauses: Dictionary = {} -var speeds: Dictionary = {} -var mutations: Array[Array] = [] -var time: String = "" - - -func _init(data: Dictionary) -> void: - text = data.text - pauses = data.pauses - speeds = data.speeds - mutations = data.mutations - time = data.time diff --git a/addons/dialogue_manager/components/resolved_tag_data.gd b/addons/dialogue_manager/components/resolved_tag_data.gd deleted file mode 100644 index 728cc42..0000000 --- a/addons/dialogue_manager/components/resolved_tag_data.gd +++ /dev/null @@ -1,10 +0,0 @@ -extends RefCounted - - -var tags: PackedStringArray = [] -var line_without_tags: String = "" - - -func _init(data: Dictionary) -> void: - tags = data.tags - line_without_tags = data.line_without_tags diff --git a/addons/dialogue_manager/components/search_and_replace.gd b/addons/dialogue_manager/components/search_and_replace.gd deleted file mode 100644 index c47ac5b..0000000 --- a/addons/dialogue_manager/components/search_and_replace.gd +++ /dev/null @@ -1,210 +0,0 @@ -@tool -extends VBoxContainer - - -signal open_requested() -signal close_requested() - - -const DialogueConstants = preload("../constants.gd") - - -@onready var input: LineEdit = $Search/Input -@onready var result_label: Label = $Search/ResultLabel -@onready var previous_button: Button = $Search/PreviousButton -@onready var next_button: Button = $Search/NextButton -@onready var match_case_button: CheckBox = $Search/MatchCaseCheckBox -@onready var replace_check_button: CheckButton = $Search/ReplaceCheckButton -@onready var replace_panel: HBoxContainer = $Replace -@onready var replace_input: LineEdit = $Replace/Input -@onready var replace_button: Button = $Replace/ReplaceButton -@onready var replace_all_button: Button = $Replace/ReplaceAllButton - -# The code edit we will be affecting (for some reason exporting this didn't work) -var code_edit: CodeEdit: - set(next_code_edit): - code_edit = next_code_edit - code_edit.gui_input.connect(_on_text_edit_gui_input) - code_edit.text_changed.connect(_on_text_edit_text_changed) - get: - return code_edit - -var results: Array = [] -var result_index: int = -1: - set(next_result_index): - result_index = next_result_index - if results.size() > 0: - var r = results[result_index] - code_edit.set_caret_line(r[0]) - code_edit.select(r[0], r[1], r[0], r[1] + r[2]) - else: - result_index = -1 - if is_instance_valid(code_edit): - code_edit.deselect() - - result_label.text = DialogueConstants.translate(&"n_of_n").format({ index = result_index + 1, total = results.size() }) - get: - return result_index - - -func _ready() -> void: - apply_theme() - - input.placeholder_text = DialogueConstants.translate(&"search.placeholder") - previous_button.tooltip_text = DialogueConstants.translate(&"search.previous") - next_button.tooltip_text = DialogueConstants.translate(&"search.next") - match_case_button.text = DialogueConstants.translate(&"search.match_case") - $Search/ReplaceCheckButton.text = DialogueConstants.translate(&"search.toggle_replace") - replace_button.text = DialogueConstants.translate(&"search.replace") - replace_all_button.text = DialogueConstants.translate(&"search.replace_all") - $Replace/ReplaceLabel.text = DialogueConstants.translate(&"search.replace_with") - - self.result_index = -1 - - replace_panel.hide() - replace_button.disabled = true - replace_all_button.disabled = true - - hide() - - -func focus_line_edit() -> void: - input.grab_focus() - input.select_all() - - -func apply_theme() -> void: - if is_instance_valid(previous_button): - previous_button.icon = get_theme_icon("ArrowLeft", "EditorIcons") - if is_instance_valid(next_button): - next_button.icon = get_theme_icon("ArrowRight", "EditorIcons") - - -# Find text in the code -func search(text: String = "", default_result_index: int = 0) -> void: - results.clear() - - if text == "": - text = input.text - - var lines = code_edit.text.split("\n") - for line_number in range(0, lines.size()): - var line = lines[line_number] - - var column = find_in_line(line, text, 0) - while column > -1: - results.append([line_number, column, text.length()]) - column = find_in_line(line, text, column + 1) - - if results.size() > 0: - replace_button.disabled = false - replace_all_button.disabled = false - else: - replace_button.disabled = true - replace_all_button.disabled = true - - self.result_index = clamp(default_result_index, 0, results.size() - 1) - - -# Find text in a string and match case if requested -func find_in_line(line: String, text: String, from_index: int = 0) -> int: - if match_case_button.button_pressed: - return line.find(text, from_index) - else: - return line.findn(text, from_index) - - -### Signals - - -func _on_text_edit_gui_input(event: InputEvent) -> void: - if event is InputEventKey and event.is_pressed(): - match event.as_text(): - "Ctrl+F", "Command+F": - open_requested.emit() - "Ctrl+Shift+R", "Command+Shift+R": - replace_check_button.set_pressed(true) - open_requested.emit() - - -func _on_text_edit_text_changed() -> void: - results.clear() - - -func _on_search_and_replace_theme_changed() -> void: - apply_theme() - - -func _on_input_text_changed(new_text: String) -> void: - search(new_text) - - -func _on_previous_button_pressed() -> void: - self.result_index = wrapi(result_index - 1, 0, results.size()) - - -func _on_next_button_pressed() -> void: - self.result_index = wrapi(result_index + 1, 0, results.size()) - - -func _on_search_and_replace_visibility_changed() -> void: - if is_instance_valid(input): - if visible: - input.grab_focus() - var selection = code_edit.get_selected_text() - if input.text == "" and selection != "": - input.text = selection - search(selection) - else: - search() - else: - input.text = "" - - -func _on_input_gui_input(event: InputEvent) -> void: - if event is InputEventKey and event.is_pressed(): - match event.as_text(): - "Enter": - search(input.text) - "Escape": - emit_signal("close_requested") - - -func _on_replace_button_pressed() -> void: - if result_index == -1: return - - # Replace the selection at result index - var r: Array = results[result_index] - var lines: PackedStringArray = code_edit.text.split("\n") - var line: String = lines[r[0]] - line = line.substr(0, r[1]) + replace_input.text + line.substr(r[1] + r[2]) - lines[r[0]] = line - code_edit.text = "\n".join(lines) - search(input.text, result_index) - code_edit.text_changed.emit() - - -func _on_replace_all_button_pressed() -> void: - if match_case_button.button_pressed: - code_edit.text = code_edit.text.replace(input.text, replace_input.text) - else: - code_edit.text = code_edit.text.replacen(input.text, replace_input.text) - search() - code_edit.text_changed.emit() - - -func _on_replace_check_button_toggled(button_pressed: bool) -> void: - replace_panel.visible = button_pressed - if button_pressed: - replace_input.grab_focus() - - -func _on_input_focus_entered() -> void: - if results.size() == 0: - search() - else: - self.result_index = result_index - - -func _on_match_case_check_box_toggled(button_pressed: bool) -> void: - search() diff --git a/addons/dialogue_manager/components/search_and_replace.tscn b/addons/dialogue_manager/components/search_and_replace.tscn deleted file mode 100644 index 82dd60d..0000000 --- a/addons/dialogue_manager/components/search_and_replace.tscn +++ /dev/null @@ -1,87 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://gr8nakpbrhby"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/search_and_replace.gd" id="1_8oj1f"] - -[node name="SearchAndReplace" type="VBoxContainer"] -visible = false -anchors_preset = 10 -anchor_right = 1.0 -offset_bottom = 31.0 -grow_horizontal = 2 -size_flags_horizontal = 3 -script = ExtResource("1_8oj1f") - -[node name="Search" type="HBoxContainer" parent="."] -layout_mode = 2 - -[node name="Input" type="LineEdit" parent="Search"] -layout_mode = 2 -size_flags_horizontal = 3 -placeholder_text = "Text to search for" -metadata/_edit_use_custom_anchors = true - -[node name="MatchCaseCheckBox" type="CheckBox" parent="Search"] -layout_mode = 2 -text = "Match case" - -[node name="VSeparator" type="VSeparator" parent="Search"] -layout_mode = 2 - -[node name="PreviousButton" type="Button" parent="Search"] -layout_mode = 2 -tooltip_text = "Previous" -flat = true - -[node name="ResultLabel" type="Label" parent="Search"] -layout_mode = 2 -text = "0 of 0" - -[node name="NextButton" type="Button" parent="Search"] -layout_mode = 2 -tooltip_text = "Next" -flat = true - -[node name="VSeparator2" type="VSeparator" parent="Search"] -layout_mode = 2 - -[node name="ReplaceCheckButton" type="CheckButton" parent="Search"] -layout_mode = 2 -text = "Replace" - -[node name="Replace" type="HBoxContainer" parent="."] -visible = false -layout_mode = 2 - -[node name="ReplaceLabel" type="Label" parent="Replace"] -layout_mode = 2 -text = "Replace with:" - -[node name="Input" type="LineEdit" parent="Replace"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="ReplaceButton" type="Button" parent="Replace"] -layout_mode = 2 -disabled = true -text = "Replace" -flat = true - -[node name="ReplaceAllButton" type="Button" parent="Replace"] -layout_mode = 2 -disabled = true -text = "Replace all" -flat = true - -[connection signal="theme_changed" from="." to="." method="_on_search_and_replace_theme_changed"] -[connection signal="visibility_changed" from="." to="." method="_on_search_and_replace_visibility_changed"] -[connection signal="focus_entered" from="Search/Input" to="." method="_on_input_focus_entered"] -[connection signal="gui_input" from="Search/Input" to="." method="_on_input_gui_input"] -[connection signal="text_changed" from="Search/Input" to="." method="_on_input_text_changed"] -[connection signal="toggled" from="Search/MatchCaseCheckBox" to="." method="_on_match_case_check_box_toggled"] -[connection signal="pressed" from="Search/PreviousButton" to="." method="_on_previous_button_pressed"] -[connection signal="pressed" from="Search/NextButton" to="." method="_on_next_button_pressed"] -[connection signal="toggled" from="Search/ReplaceCheckButton" to="." method="_on_replace_check_button_toggled"] -[connection signal="focus_entered" from="Replace/Input" to="." method="_on_input_focus_entered"] -[connection signal="gui_input" from="Replace/Input" to="." method="_on_input_gui_input"] -[connection signal="pressed" from="Replace/ReplaceButton" to="." method="_on_replace_button_pressed"] -[connection signal="pressed" from="Replace/ReplaceAllButton" to="." method="_on_replace_all_button_pressed"] diff --git a/addons/dialogue_manager/components/title_list.gd b/addons/dialogue_manager/components/title_list.gd deleted file mode 100644 index ee7cd13..0000000 --- a/addons/dialogue_manager/components/title_list.gd +++ /dev/null @@ -1,67 +0,0 @@ -@tool -extends VBoxContainer - -signal title_selected(title: String) - - -const DialogueConstants = preload("../constants.gd") - - -@onready var filter_edit: LineEdit = $FilterEdit -@onready var list: ItemList = $List - -var titles: PackedStringArray: - set(next_titles): - titles = next_titles - apply_filter() - get: - return titles - -var filter: String: - set(next_filter): - filter = next_filter - apply_filter() - get: - return filter - - -func _ready() -> void: - apply_theme() - - filter_edit.placeholder_text = DialogueConstants.translate(&"titles_list.filter") - - -func select_title(title: String) -> void: - list.deselect_all() - for i in range(0, list.get_item_count()): - if list.get_item_text(i) == title.strip_edges(): - list.select(i) - - -func apply_filter() -> void: - list.clear() - for title in titles: - if filter == "" or filter.to_lower() in title.to_lower(): - list.add_item(title.strip_edges()) - - -func apply_theme() -> void: - if is_instance_valid(filter_edit): - filter_edit.right_icon = get_theme_icon("Search", "EditorIcons") - - -### Signals - - -func _on_theme_changed() -> void: - apply_theme() - - -func _on_filter_edit_text_changed(new_text: String) -> void: - self.filter = new_text - - -func _on_list_item_clicked(index: int, at_position: Vector2, mouse_button_index: int) -> void: - if mouse_button_index == MOUSE_BUTTON_LEFT: - var title = list.get_item_text(index) - title_selected.emit(title) diff --git a/addons/dialogue_manager/components/title_list.tscn b/addons/dialogue_manager/components/title_list.tscn deleted file mode 100644 index 3e5c9a0..0000000 --- a/addons/dialogue_manager/components/title_list.tscn +++ /dev/null @@ -1,45 +0,0 @@ -[gd_scene load_steps=4 format=3 uid="uid://ctns6ouwwd68i"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/title_list.gd" id="1_5qqmd"] - -[sub_resource type="Image" id="Image_o5dqs"] -data = { -"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), -"format": "RGBA8", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_ekmpw"] -image = SubResource("Image_o5dqs") - -[node name="TitleList" type="VBoxContainer"] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -script = ExtResource("1_5qqmd") - -[node name="FilterEdit" type="LineEdit" parent="."] -layout_mode = 2 -offset_right = 1152.0 -offset_bottom = 31.0 -placeholder_text = "Filter titles" -clear_button_enabled = true -right_icon = SubResource("ImageTexture_ekmpw") - -[node name="List" type="ItemList" parent="."] -layout_mode = 2 -offset_top = 35.0 -offset_right = 1152.0 -offset_bottom = 648.0 -size_flags_vertical = 3 -allow_reselect = true - -[connection signal="theme_changed" from="." to="." method="_on_theme_changed"] -[connection signal="text_changed" from="FilterEdit" to="." method="_on_filter_edit_text_changed"] -[connection signal="item_clicked" from="List" to="." method="_on_list_item_clicked"] diff --git a/addons/dialogue_manager/components/update_button.gd b/addons/dialogue_manager/components/update_button.gd deleted file mode 100644 index b8c2809..0000000 --- a/addons/dialogue_manager/components/update_button.gd +++ /dev/null @@ -1,126 +0,0 @@ -@tool -extends Button - -const DialogueConstants = preload("../constants.gd") -const DialogueSettings = preload("../settings.gd") - -const REMOTE_RELEASES_URL = "https://api.github.com/repos/nathanhoad/godot_dialogue_manager/releases" - - -@onready var http_request: HTTPRequest = $HTTPRequest -@onready var download_dialog: AcceptDialog = $DownloadDialog -@onready var download_update_panel = $DownloadDialog/DownloadUpdatePanel -@onready var needs_reload_dialog: AcceptDialog = $NeedsReloadDialog -@onready var update_failed_dialog: AcceptDialog = $UpdateFailedDialog -@onready var timer: Timer = $Timer - -# The main editor plugin -var editor_plugin: EditorPlugin - -var needs_reload: bool = false - -# A lambda that gets called just before refreshing the plugin. Return false to stop the reload. -var on_before_refresh: Callable = func(): return true - - -func _ready() -> void: - hide() - apply_theme() - - # Check for updates on GitHub - check_for_update() - - # Check again every few hours - timer.start(60 * 60 * 12) - - -# Convert a version number to an actually comparable number -func version_to_number(version: String) -> int: - var bits = version.split(".") - return bits[0].to_int() * 1000000 + bits[1].to_int() * 1000 + bits[2].to_int() - - -func apply_theme() -> void: - var color: Color = get_theme_color("success_color", "Editor") - - if needs_reload: - color = get_theme_color("error_color", "Editor") - icon = get_theme_icon("Reload", "EditorIcons") - add_theme_color_override("icon_normal_color", color) - add_theme_color_override("icon_focus_color", color) - add_theme_color_override("icon_hover_color", color) - - add_theme_color_override("font_color", color) - add_theme_color_override("font_focus_color", color) - add_theme_color_override("font_hover_color", color) - - -func check_for_update() -> void: - if DialogueSettings.get_user_value("check_for_updates", true): - http_request.request(REMOTE_RELEASES_URL) - - -### Signals - - -func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void: - if result != HTTPRequest.RESULT_SUCCESS: return - - var current_version: String = editor_plugin.get_version() - - # Work out the next version from the releases information on GitHub - var response = JSON.parse_string(body.get_string_from_utf8()) - if typeof(response) != TYPE_ARRAY: return - - # GitHub releases are in order of creation, not order of version - var versions = (response as Array).filter(func(release): - var version: String = release.tag_name.substr(1) - return version_to_number(version) > version_to_number(current_version) - ) - if versions.size() > 0: - download_update_panel.next_version_release = versions[0] - text = DialogueConstants.translate(&"update.available").format({ version = versions[0].tag_name.substr(1) }) - show() - - -func _on_update_button_pressed() -> void: - if needs_reload: - var will_refresh = on_before_refresh.call() - if will_refresh: - editor_plugin.get_editor_interface().restart_editor(true) - else: - var scale: float = editor_plugin.get_editor_interface().get_editor_scale() - download_dialog.min_size = Vector2(300, 250) * scale - download_dialog.popup_centered() - - -func _on_download_dialog_close_requested() -> void: - download_dialog.hide() - - -func _on_download_update_panel_updated(updated_to_version: String) -> void: - download_dialog.hide() - - needs_reload_dialog.dialog_text = DialogueConstants.translate(&"update.needs_reload") - needs_reload_dialog.ok_button_text = DialogueConstants.translate(&"update.reload_ok_button") - needs_reload_dialog.cancel_button_text = DialogueConstants.translate(&"update.reload_cancel_button") - needs_reload_dialog.popup_centered() - - needs_reload = true - text = DialogueConstants.translate(&"update.reload_project") - apply_theme() - - -func _on_download_update_panel_failed() -> void: - download_dialog.hide() - update_failed_dialog.dialog_text = DialogueConstants.translate(&"update.failed") - update_failed_dialog.popup_centered() - - -func _on_needs_reload_dialog_confirmed() -> void: - editor_plugin.get_editor_interface().restart_editor(true) - - -func _on_timer_timeout() -> void: - if not needs_reload: - check_for_update() diff --git a/addons/dialogue_manager/components/update_button.tscn b/addons/dialogue_manager/components/update_button.tscn deleted file mode 100644 index 533a94e..0000000 --- a/addons/dialogue_manager/components/update_button.tscn +++ /dev/null @@ -1,42 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://co8yl23idiwbi"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/update_button.gd" id="1_d2tpb"] -[ext_resource type="PackedScene" uid="uid://qdxrxv3c3hxk" path="res://addons/dialogue_manager/components/download_update_panel.tscn" id="2_iwm7r"] - -[node name="UpdateButton" type="Button"] -visible = false -offset_right = 8.0 -offset_bottom = 8.0 -theme_override_colors/font_color = Color(0, 0, 0, 1) -theme_override_colors/font_hover_color = Color(0, 0, 0, 1) -theme_override_colors/font_focus_color = Color(0, 0, 0, 1) -text = "v2.9.0 available" -flat = true -script = ExtResource("1_d2tpb") - -[node name="HTTPRequest" type="HTTPRequest" parent="."] - -[node name="DownloadDialog" type="AcceptDialog" parent="."] -title = "Download update" -size = Vector2i(400, 300) -unresizable = true -min_size = Vector2i(300, 250) -ok_button_text = "Close" - -[node name="DownloadUpdatePanel" parent="DownloadDialog" instance=ExtResource("2_iwm7r")] - -[node name="UpdateFailedDialog" type="AcceptDialog" parent="."] -dialog_text = "You have been updated to version 2.4.3" - -[node name="NeedsReloadDialog" type="ConfirmationDialog" parent="."] - -[node name="Timer" type="Timer" parent="."] -wait_time = 14400.0 - -[connection signal="pressed" from="." to="." method="_on_update_button_pressed"] -[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_request_completed"] -[connection signal="close_requested" from="DownloadDialog" to="." method="_on_download_dialog_close_requested"] -[connection signal="failed" from="DownloadDialog/DownloadUpdatePanel" to="." method="_on_download_update_panel_failed"] -[connection signal="updated" from="DownloadDialog/DownloadUpdatePanel" to="." method="_on_download_update_panel_updated"] -[connection signal="confirmed" from="NeedsReloadDialog" to="." method="_on_needs_reload_dialog_confirmed"] -[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"] diff --git a/addons/dialogue_manager/constants.gd b/addons/dialogue_manager/constants.gd deleted file mode 100644 index bc93d21..0000000 --- a/addons/dialogue_manager/constants.gd +++ /dev/null @@ -1,187 +0,0 @@ -extends Node - - -const USER_CONFIG_PATH = "user://dialogue_manager_user_config.json" -const CACHE_PATH = "user://dialogue_manager_cache.json" - -# Token types - -const TOKEN_FUNCTION = &"function" -const TOKEN_DICTIONARY_REFERENCE = &"dictionary_reference" -const TOKEN_DICTIONARY_NESTED_REFERENCE = &"dictionary_nested_reference" -const TOKEN_GROUP = &"group" -const TOKEN_ARRAY = &"array" -const TOKEN_DICTIONARY = &"dictionary" -const TOKEN_PARENS_OPEN = &"parens_open" -const TOKEN_PARENS_CLOSE = &"parens_close" -const TOKEN_BRACKET_OPEN = &"bracket_open" -const TOKEN_BRACKET_CLOSE = &"bracket_close" -const TOKEN_BRACE_OPEN = &"brace_open" -const TOKEN_BRACE_CLOSE = &"brace_close" -const TOKEN_COLON = &"colon" -const TOKEN_COMPARISON = &"comparison" -const TOKEN_ASSIGNMENT = &"assignment" -const TOKEN_OPERATOR = &"operator" -const TOKEN_COMMA = &"comma" -const TOKEN_DOT = &"dot" -const TOKEN_CONDITION = &"condition" -const TOKEN_BOOL = &"bool" -const TOKEN_NOT = &"not" -const TOKEN_AND_OR = &"and_or" -const TOKEN_STRING = &"string" -const TOKEN_NUMBER = &"number" -const TOKEN_VARIABLE = &"variable" -const TOKEN_COMMENT = &"comment" - -const TOKEN_ERROR = &"error" - -# Line types - -const TYPE_UNKNOWN = &"unknown" -const TYPE_RESPONSE = &"response" -const TYPE_TITLE = &"title" -const TYPE_CONDITION = &"condition" -const TYPE_MUTATION = &"mutation" -const TYPE_GOTO = &"goto" -const TYPE_DIALOGUE = &"dialogue" -const TYPE_ERROR = &"error" - -const TYPE_ELSE = &"else" - -# Line IDs - -const ID_NULL = &"" -const ID_ERROR = &"error" -const ID_ERROR_INVALID_TITLE = &"invalid title" -const ID_ERROR_TITLE_HAS_NO_BODY = &"title has no body" -const ID_END = &"end" -const ID_END_CONVERSATION = &"end!" - -# Errors - -const ERR_ERRORS_IN_IMPORTED_FILE = 100 -const ERR_FILE_ALREADY_IMPORTED = 101 -const ERR_DUPLICATE_IMPORT_NAME = 102 -const ERR_EMPTY_TITLE = 103 -const ERR_DUPLICATE_TITLE = 104 -const ERR_NESTED_TITLE = 105 -const ERR_TITLE_INVALID_CHARACTERS = 106 -const ERR_UNKNOWN_TITLE = 107 -const ERR_INVALID_TITLE_REFERENCE = 108 -const ERR_TITLE_REFERENCE_HAS_NO_CONTENT = 109 -const ERR_INVALID_EXPRESSION = 110 -const ERR_UNEXPECTED_CONDITION = 111 -const ERR_DUPLICATE_ID = 112 -const ERR_MISSING_ID = 113 -const ERR_INVALID_INDENTATION = 114 -const ERR_INVALID_CONDITION_INDENTATION = 115 -const ERR_INCOMPLETE_EXPRESSION = 116 -const ERR_INVALID_EXPRESSION_FOR_VALUE = 117 -const ERR_UNKNOWN_LINE_SYNTAX = 118 -const ERR_TITLE_BEGINS_WITH_NUMBER = 119 -const ERR_UNEXPECTED_END_OF_EXPRESSION = 120 -const ERR_UNEXPECTED_FUNCTION = 121 -const ERR_UNEXPECTED_BRACKET = 122 -const ERR_UNEXPECTED_CLOSING_BRACKET = 123 -const ERR_MISSING_CLOSING_BRACKET = 124 -const ERR_UNEXPECTED_OPERATOR = 125 -const ERR_UNEXPECTED_COMMA = 126 -const ERR_UNEXPECTED_COLON = 127 -const ERR_UNEXPECTED_DOT = 128 -const ERR_UNEXPECTED_BOOLEAN = 129 -const ERR_UNEXPECTED_STRING = 130 -const ERR_UNEXPECTED_NUMBER = 131 -const ERR_UNEXPECTED_VARIABLE = 132 -const ERR_INVALID_INDEX = 133 -const ERR_UNEXPECTED_ASSIGNMENT = 134 -const ERR_UNKNOWN_USING = 135 - - -## Get the error message -static func get_error_message(error: int) -> String: - match error: - ERR_ERRORS_IN_IMPORTED_FILE: - return translate(&"errors.import_errors") - ERR_FILE_ALREADY_IMPORTED: - return translate(&"errors.already_imported") - ERR_DUPLICATE_IMPORT_NAME: - return translate(&"errors.duplicate_import") - ERR_EMPTY_TITLE: - return translate(&"errors.empty_title") - ERR_DUPLICATE_TITLE: - return translate(&"errors.duplicate_title") - ERR_NESTED_TITLE: - return translate(&"errors.nested_title") - ERR_TITLE_INVALID_CHARACTERS: - return translate(&"errors.invalid_title_string") - ERR_TITLE_BEGINS_WITH_NUMBER: - return translate(&"errors.invalid_title_number") - ERR_UNKNOWN_TITLE: - return translate(&"errors.unknown_title") - ERR_INVALID_TITLE_REFERENCE: - return translate(&"errors.jump_to_invalid_title") - ERR_TITLE_REFERENCE_HAS_NO_CONTENT: - return translate(&"errors.title_has_no_content") - ERR_INVALID_EXPRESSION: - return translate(&"errors.invalid_expression") - ERR_UNEXPECTED_CONDITION: - return translate(&"errors.unexpected_condition") - ERR_DUPLICATE_ID: - return translate(&"errors.duplicate_id") - ERR_MISSING_ID: - return translate(&"errors.missing_id") - ERR_INVALID_INDENTATION: - return translate(&"errors.invalid_indentation") - ERR_INVALID_CONDITION_INDENTATION: - return translate(&"errors.condition_has_no_content") - ERR_INCOMPLETE_EXPRESSION: - return translate(&"errors.incomplete_expression") - ERR_INVALID_EXPRESSION_FOR_VALUE: - return translate(&"errors.invalid_expression_for_value") - ERR_FILE_NOT_FOUND: - return translate(&"errors.file_not_found") - ERR_UNEXPECTED_END_OF_EXPRESSION: - return translate(&"errors.unexpected_end_of_expression") - ERR_UNEXPECTED_FUNCTION: - return translate(&"errors.unexpected_function") - ERR_UNEXPECTED_BRACKET: - return translate(&"errors.unexpected_bracket") - ERR_UNEXPECTED_CLOSING_BRACKET: - return translate(&"errors.unexpected_closing_bracket") - ERR_MISSING_CLOSING_BRACKET: - return translate(&"errors.missing_closing_bracket") - ERR_UNEXPECTED_OPERATOR: - return translate(&"errors.unexpected_operator") - ERR_UNEXPECTED_COMMA: - return translate(&"errors.unexpected_comma") - ERR_UNEXPECTED_COLON: - return translate(&"errors.unexpected_colon") - ERR_UNEXPECTED_DOT: - return translate(&"errors.unexpected_dot") - ERR_UNEXPECTED_BOOLEAN: - return translate(&"errors.unexpected_boolean") - ERR_UNEXPECTED_STRING: - return translate(&"errors.unexpected_string") - ERR_UNEXPECTED_NUMBER: - return translate(&"errors.unexpected_number") - ERR_UNEXPECTED_VARIABLE: - return translate(&"errors.unexpected_variable") - ERR_INVALID_INDEX: - return translate(&"errors.invalid_index") - ERR_UNEXPECTED_ASSIGNMENT: - return translate(&"errors.unexpected_assignment") - ERR_UNKNOWN_USING: - return translate(&"errors.unknown_using") - - return translate(&"errors.unknown") - - -static func translate(string: String) -> String: - var base_path = new().get_script().resource_path.get_base_dir() - - var language: String = TranslationServer.get_tool_locale() - var translations_path: String = "%s/l10n/%s.po" % [base_path, language] - var fallback_translations_path: String = "%s/l10n/%s.po" % [base_path, TranslationServer.get_tool_locale().substr(0, 2)] - var en_translations_path: String = "%s/l10n/en.po" % base_path - var translations: Translation = load(translations_path if FileAccess.file_exists(translations_path) else (fallback_translations_path if FileAccess.file_exists(fallback_translations_path) else en_translations_path)) - return translations.get_message(string) diff --git a/addons/dialogue_manager/dialogue_label.gd b/addons/dialogue_manager/dialogue_label.gd deleted file mode 100644 index 24057be..0000000 --- a/addons/dialogue_manager/dialogue_label.gd +++ /dev/null @@ -1,226 +0,0 @@ -@icon("./assets/icon.svg") - -@tool - -## A RichTextLabel specifically for use with [b]Dialogue Manager[/b] dialogue. -class_name DialogueLabel extends RichTextLabel - - -## Emitted for each letter typed out. -signal spoke(letter: String, letter_index: int, speed: float) - -## Emitted when typing paused for a `[wait]` -signal paused_typing(duration: float) - -## Emitted when the player skips the typing of dialogue. -signal skipped_typing() - -## Emitted when typing finishes. -signal finished_typing() - - -# The action to press to skip typing. -@export var skip_action: StringName = &"ui_cancel" - -## The speed with which the text types out. -@export var seconds_per_step: float = 0.02 - -## Automatically have a brief pause when these characters are encountered. -@export var pause_at_characters: String = ".?!" - -## Don't auto pause if the charcter after the pause is one of these. -@export var skip_pause_at_character_if_followed_by: String = ")\"" - -## Don't auto pause after these abbreviations (only if "." is in `pause_at_characters`).[br] -## Abbreviations are limitted to 5 characters in length [br] -## Does not support multi-period abbreviations (ex. "p.m.") -@export var skip_pause_at_abbreviations: PackedStringArray = ["Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex"] - -## The amount of time to pause when exposing a character present in pause_at_characters. -@export var seconds_per_pause_step: float = 0.3 - - -## The current line of dialogue. -var dialogue_line: - set(next_dialogue_line): - dialogue_line = next_dialogue_line - custom_minimum_size = Vector2.ZERO - text = dialogue_line.text - get: - return dialogue_line - -## Whether the label is currently typing itself out. -var is_typing: bool = false: - set(value): - var is_finished: bool = is_typing != value and value == false - is_typing = value - if is_finished: - finished_typing.emit() - get: - return is_typing - -var _last_wait_index: int = -1 -var _last_mutation_index: int = -1 -var _waiting_seconds: float = 0 -var _is_awaiting_mutation: bool = false - - -func _process(delta: float) -> void: - if self.is_typing: - # Type out text - if visible_ratio < 1: - # See if we are waiting - if _waiting_seconds > 0: - _waiting_seconds = _waiting_seconds - delta - # If we are no longer waiting then keep typing - if _waiting_seconds <= 0: - _type_next(delta, _waiting_seconds) - else: - # Make sure any mutations at the end of the line get run - _mutate_inline_mutations(get_total_character_count()) - self.is_typing = false - - -func _unhandled_input(event: InputEvent) -> void: - # Note: this will no longer be reached if using Dialogue Manager > 2.32.2. To make skip handling - # simpler (so all of mouse/keyboard/joypad are together) it is now the responsibility of the - # dialogue balloon. - if self.is_typing and visible_ratio < 1 and InputMap.has_action(skip_action) and event.is_action_pressed(skip_action): - get_viewport().set_input_as_handled() - skip_typing() - - -## Start typing out the text -func type_out() -> void: - text = dialogue_line.text - visible_characters = 0 - visible_ratio = 0 - _waiting_seconds = 0 - _last_wait_index = -1 - _last_mutation_index = -1 - - self.is_typing = true - - # Allow typing listeners a chance to connect - await get_tree().process_frame - - if get_total_character_count() == 0: - self.is_typing = false - elif seconds_per_step == 0: - _mutate_remaining_mutations() - visible_characters = get_total_character_count() - self.is_typing = false - - -## Stop typing out the text and jump right to the end -func skip_typing() -> void: - _mutate_remaining_mutations() - visible_characters = get_total_character_count() - self.is_typing = false - skipped_typing.emit() - - -# Type out the next character(s) -func _type_next(delta: float, seconds_needed: float) -> void: - if _is_awaiting_mutation: return - - if visible_characters == get_total_character_count(): - return - - if _last_mutation_index != visible_characters: - _last_mutation_index = visible_characters - _mutate_inline_mutations(visible_characters) - if _is_awaiting_mutation: return - - var additional_waiting_seconds: float = _get_pause(visible_characters) - - # Pause on characters like "." - if _should_auto_pause(): - additional_waiting_seconds += seconds_per_pause_step - - # Pause at literal [wait] directives - if _last_wait_index != visible_characters and additional_waiting_seconds > 0: - _last_wait_index = visible_characters - _waiting_seconds += additional_waiting_seconds - paused_typing.emit(_get_pause(visible_characters)) - else: - visible_characters += 1 - if visible_characters <= get_total_character_count(): - spoke.emit(get_parsed_text()[visible_characters - 1], visible_characters - 1, _get_speed(visible_characters)) - # See if there's time to type out some more in this frame - seconds_needed += seconds_per_step * (1.0 / _get_speed(visible_characters)) - if seconds_needed > delta: - _waiting_seconds += seconds_needed - else: - _type_next(delta, seconds_needed) - - -# Get the pause for the current typing position if there is one -func _get_pause(at_index: int) -> float: - return dialogue_line.pauses.get(at_index, 0) - - -# Get the speed for the current typing position -func _get_speed(at_index: int) -> float: - var speed: float = 1 - for index in dialogue_line.speeds: - if index > at_index: - return speed - speed = dialogue_line.speeds[index] - return speed - - -# Run any inline mutations that haven't been run yet -func _mutate_remaining_mutations() -> void: - for i in range(visible_characters, get_total_character_count() + 1): - _mutate_inline_mutations(i) - - -# Run any mutations at the current typing position -func _mutate_inline_mutations(index: int) -> void: - for inline_mutation in dialogue_line.inline_mutations: - # inline mutations are an array of arrays in the form of [character index, resolvable function] - if inline_mutation[0] > index: - return - if inline_mutation[0] == index: - _is_awaiting_mutation = true - # The DialogueManager can't be referenced directly here so we need to get it by its path - await Engine.get_singleton("DialogueManager").mutate(inline_mutation[1], dialogue_line.extra_game_states, true) - _is_awaiting_mutation = false - - -# Determine if the current autopause character at the cursor should qualify to pause typing. -func _should_auto_pause() -> bool: - if visible_characters == 0: return false - - var parsed_text: String = get_parsed_text() - - # Avoid outofbounds when the label auto-translates and the text changes to one shorter while typing out - # Note: visible characters can be larger than parsed_text after a translation event - if visible_characters >= parsed_text.length(): return false - - # Ignore pause characters if they are next to a non-pause character - if parsed_text[visible_characters] in skip_pause_at_character_if_followed_by.split(): - return false - - # Ignore "." if it's between two numbers - if visible_characters > 3 and parsed_text[visible_characters - 1] == ".": - var possible_number: String = parsed_text.substr(visible_characters - 2, 3) - if str(float(possible_number)) == possible_number: - return false - - # Ignore "." if it's used in an abbreviation - # Note: does NOT support multi-period abbreviations (ex. p.m.) - if "." in pause_at_characters and parsed_text[visible_characters - 1] == ".": - for abbreviation in skip_pause_at_abbreviations: - if visible_characters >= abbreviation.length(): - var previous_characters: String = parsed_text.substr(visible_characters - abbreviation.length() - 1, abbreviation.length()) - if previous_characters == abbreviation: - return false - - # Ignore two non-"." characters next to each other - var other_pause_characters: PackedStringArray = pause_at_characters.replace(".", "").split() - if visible_characters > 1 and parsed_text[visible_characters - 1] in other_pause_characters and parsed_text[visible_characters] in other_pause_characters: - return false - - return parsed_text[visible_characters - 1] in pause_at_characters.split() diff --git a/addons/dialogue_manager/dialogue_label.tscn b/addons/dialogue_manager/dialogue_label.tscn deleted file mode 100644 index df48b64..0000000 --- a/addons/dialogue_manager/dialogue_label.tscn +++ /dev/null @@ -1,19 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://ckvgyvclnwggo"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_label.gd" id="1_cital"] - -[node name="DialogueLabel" type="RichTextLabel"] -anchors_preset = 10 -anchor_right = 1.0 -grow_horizontal = 2 -mouse_filter = 1 -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 = 1 -script = ExtResource("1_cital") -skip_pause_at_abbreviations = PackedStringArray("Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex") diff --git a/addons/dialogue_manager/dialogue_line.gd b/addons/dialogue_manager/dialogue_line.gd deleted file mode 100644 index a9bf84a..0000000 --- a/addons/dialogue_manager/dialogue_line.gd +++ /dev/null @@ -1,98 +0,0 @@ -## A line of dialogue returned from [code]DialogueManager[/code]. -class_name DialogueLine extends RefCounted - - -const _DialogueConstants = preload("./constants.gd") - - -## The ID of this line -var id: String - -## The internal type of this dialogue object. One of [code]TYPE_DIALOGUE[/code] or [code]TYPE_MUTATION[/code] -var type: String = _DialogueConstants.TYPE_DIALOGUE - -## The next line ID after this line. -var next_id: String = "" - -## The character name that is saying this line. -var character: String = "" - -## A dictionary of variable replacements fo the character name. Generally for internal use only. -var character_replacements: Array[Dictionary] = [] - -## The dialogue being spoken. -var text: String = "" - -## A dictionary of replacements for the text. Generally for internal use only. -var text_replacements: Array[Dictionary] = [] - -## The key to use for translating this line. -var translation_key: String = "" - -## A map for when and for how long to pause while typing out the dialogue text. -var pauses: Dictionary = {} - -## A map for speed changes when typing out the dialogue text. -var speeds: Dictionary = {} - -## A map of any mutations to run while typing out the dialogue text. -var inline_mutations: Array[Array] = [] - -## A list of responses attached to this line of dialogue. -var responses: Array[DialogueResponse] = [] - -## A list of any extra game states to check when resolving variables and mutations. -var extra_game_states: Array = [] - -## How long to show this line before advancing to the next. Either a float (of seconds), [code]"auto"[/code], or [code]null[/code]. -var time: String = "" - -## Any #tags that were included in the line -var tags: PackedStringArray = [] - -## The mutation details if this is a mutation line (where [code]type == TYPE_MUTATION[/code]). -var mutation: Dictionary = {} - -## The conditions to check before including this line in the flow of dialogue. If failed the line will be skipped over. -var conditions: Dictionary = {} - - -func _init(data: Dictionary = {}) -> void: - if data.size() > 0: - id = data.id - next_id = data.next_id - type = data.type - extra_game_states = data.get("extra_game_states", []) - - match type: - _DialogueConstants.TYPE_DIALOGUE: - character = data.character - character_replacements = data.get("character_replacements", [] as Array[Dictionary]) - text = data.text - text_replacements = data.get("text_replacements", [] as Array[Dictionary]) - translation_key = data.get("translation_key", data.text) - pauses = data.get("pauses", {}) - speeds = data.get("speeds", {}) - inline_mutations = data.get("inline_mutations", [] as Array[Array]) - time = data.get("time", "") - tags = data.get("tags", []) - - _DialogueConstants.TYPE_MUTATION: - mutation = data.mutation - - -func _to_string() -> String: - match type: - _DialogueConstants.TYPE_DIALOGUE: - return "<DialogueLine character=\"%s\" text=\"%s\">" % [character, text] - _DialogueConstants.TYPE_MUTATION: - return "<DialogueLine mutation>" - return "" - - -func get_tag_value(tag_name: String) -> String: - var wrapped := "%s=" % tag_name - for t in tags: - if t.begins_with(wrapped): - return t.replace(wrapped, "").strip_edges() - return "" diff --git a/addons/dialogue_manager/dialogue_manager.gd b/addons/dialogue_manager/dialogue_manager.gd deleted file mode 100644 index 57d7f86..0000000 --- a/addons/dialogue_manager/dialogue_manager.gd +++ /dev/null @@ -1,1235 +0,0 @@ -extends Node - - -const DialogueConstants = preload("./constants.gd") -const Builtins = preload("./utilities/builtins.gd") -const DialogueSettings = preload("./settings.gd") -const DialogueResource = preload("./dialogue_resource.gd") -const DialogueLine = preload("./dialogue_line.gd") -const DialogueResponse = preload("./dialogue_response.gd") -const DialogueManagerParser = preload("./components/parser.gd") -const DialogueManagerParseResult = preload("./components/parse_result.gd") -const ResolvedLineData = preload("./components/resolved_line_data.gd") - - -## Emitted when a title is encountered while traversing dialogue, usually when jumping from a -## goto line -signal passed_title(title: String) - -## Emitted when a line of dialogue is encountered. -signal got_dialogue(line: DialogueLine) - -## Emitted when a mutation is encountered. -signal mutated(mutation: Dictionary) - -## Emitted when some dialogue has reached the end. -signal dialogue_ended(resource: DialogueResource) - -## Used internally. -signal bridge_get_next_dialogue_line_completed(line: DialogueLine) - -## Used inernally -signal bridge_mutated() - - -enum MutationBehaviour { - Wait, - DoNotWait, - Skip -} - -enum TranslationSource { - None, - Guess, - CSV, - PO -} - - -## The list of globals that dialogue can query -var game_states: Array = [] - -## Allow dialogue to call singletons -var include_singletons: bool = true - -## Allow dialogue to call static methods/properties on classes -var include_classes: bool = true - -## Manage translation behaviour -var translation_source: TranslationSource = TranslationSource.Guess - -## Used to resolve the current scene. Override if your game manages the current scene itself. -var get_current_scene: Callable = func(): - var current_scene: Node = get_tree().current_scene - if current_scene == null: - current_scene = get_tree().root.get_child(get_tree().root.get_child_count() - 1) - return current_scene - -var _has_loaded_autoloads: bool = false -var _autoloads: Dictionary = {} - - -var _node_properties: Array = [] - - -func _ready() -> void: - # Cache the known Node2D properties - _node_properties = ["Script Variables"] - var temp_node: Node2D = Node2D.new() - for property in temp_node.get_property_list(): - _node_properties.append(property.name) - temp_node.free() - - # Make the dialogue manager available as a singleton - if Engine.has_singleton("DialogueManager"): - Engine.unregister_singleton("DialogueManager") - Engine.register_singleton("DialogueManager", self) - - # Connect up the C# signals if need be - if DialogueSettings.has_dotnet_solution(): - _get_dotnet_dialogue_manager().Prepare() - - -## Step through lines and run any mutations until we either hit some dialogue or the end of the conversation -func get_next_dialogue_line(resource: DialogueResource, key: String = "", extra_game_states: Array = [], mutation_behaviour: MutationBehaviour = MutationBehaviour.Wait) -> DialogueLine: - # You have to provide a valid dialogue resource - if resource == null: - assert(false, DialogueConstants.translate(&"runtime.no_resource")) - if resource.lines.size() == 0: - assert(false, DialogueConstants.translate(&"runtime.no_content").format({ file_path = resource.resource_path })) - - # Inject any "using" states into the game_states - for state_name in resource.using_states: - var autoload = get_tree().root.get_node_or_null(state_name) - if autoload == null: - printerr(DialogueConstants.translate(&"runtime.unknown_autoload").format({ autoload = state_name })) - else: - extra_game_states = [autoload] + extra_game_states - - # Get the line data - var dialogue: DialogueLine = await get_line(resource, key, extra_game_states) - - # If our dialogue is nothing then we hit the end - if not is_valid(dialogue): - (func(): dialogue_ended.emit(resource)).call_deferred() - return null - - # Run the mutation if it is one - if dialogue.type == DialogueConstants.TYPE_MUTATION: - var actual_next_id: String = dialogue.next_id.split(",")[0] - match mutation_behaviour: - MutationBehaviour.Wait: - await mutate(dialogue.mutation, extra_game_states) - MutationBehaviour.DoNotWait: - mutate(dialogue.mutation, extra_game_states) - MutationBehaviour.Skip: - pass - if actual_next_id in [DialogueConstants.ID_END_CONVERSATION, DialogueConstants.ID_NULL, null]: - # End the conversation - (func(): dialogue_ended.emit(resource)).call_deferred() - return null - else: - return await get_next_dialogue_line(resource, dialogue.next_id, extra_game_states, mutation_behaviour) - else: - got_dialogue.emit(dialogue) - return dialogue - - -func get_resolved_line_data(data: Dictionary, extra_game_states: Array = []) -> ResolvedLineData: - var text: String = translate(data) - - # Resolve variables - for replacement in data.text_replacements: - var value = await resolve(replacement.expression.duplicate(true), extra_game_states) - var index: int = text.find(replacement.value_in_text) - text = text.substr(0, index) + str(value) + text.substr(index + replacement.value_in_text.length()) - - var parser: DialogueManagerParser = DialogueManagerParser.new() - - # Resolve random groups - for found in parser.INLINE_RANDOM_REGEX.search_all(text): - var options = found.get_string(&"options").split(&"|") - text = text.replace(&"[[%s]]" % found.get_string(&"options"), options[randi_range(0, options.size() - 1)]) - - # Do a pass on the markers to find any conditionals - var markers: ResolvedLineData = parser.extract_markers(text) - - # Resolve any conditionals and update marker positions as needed - if data.type == DialogueConstants.TYPE_DIALOGUE: - var resolved_text: String = markers.text - var conditionals: Array[RegExMatch] = parser.INLINE_CONDITIONALS_REGEX.search_all(resolved_text) - var replacements: Array = [] - for conditional in conditionals: - var condition_raw: String = conditional.strings[conditional.names.condition] - var body: String = conditional.strings[conditional.names.body] - var body_else: String = "" - if &"[else]" in body: - var bits = body.split(&"[else]") - body = bits[0] - body_else = bits[1] - var condition: Dictionary = parser.extract_condition("if " + condition_raw, false, 0) - # If the condition fails then use the else of "" - if not await check_condition({ condition = condition }, extra_game_states): - body = body_else - replacements.append({ - start = conditional.get_start(), - end = conditional.get_end(), - string = conditional.get_string(), - body = body - }) - - for i in range(replacements.size() -1, -1, -1): - var r: Dictionary = replacements[i] - resolved_text = resolved_text.substr(0, r.start) + r.body + resolved_text.substr(r.end, 9999) - # Move any other markers now that the text has changed - var offset: int = r.end - r.start - r.body.length() - for key in [&"pauses", &"speeds", &"time"]: - if markers.get(key) == null: continue - var marker = markers.get(key) - var next_marker: Dictionary = {} - for index in marker: - if index < r.start: - next_marker[index] = marker[index] - elif index > r.start: - next_marker[index - offset] = marker[index] - markers.set(key, next_marker) - var mutations: Array[Array] = markers.mutations - var next_mutations: Array[Array] = [] - for mutation in mutations: - var index = mutation[0] - if index < r.start: - next_mutations.append(mutation) - elif index > r.start: - next_mutations.append([index - offset, mutation[1]]) - markers.mutations = next_mutations - - markers.text = resolved_text - - parser.free() - - return markers - - -## Replace any variables, etc in the character name -func get_resolved_character(data: Dictionary, extra_game_states: Array = []) -> String: - var character: String = data.get(&"character", "") - - # Resolve variables - for replacement in data.get(&"character_replacements", []): - var value = await resolve(replacement.expression.duplicate(true), extra_game_states) - var index: int = character.find(replacement.value_in_text) - character = character.substr(0, index) + str(value) + character.substr(index + replacement.value_in_text.length()) - - # Resolve random groups - var random_regex: RegEx = RegEx.new() - random_regex.compile("\\[\\[(?<options>.*?)\\]\\]") - for found in random_regex.search_all(character): - var options = found.get_string(&"options").split("|") - character = character.replace("[[%s]]" % found.get_string(&"options"), options[randi_range(0, options.size() - 1)]) - - return character - - -## Generate a dialogue resource on the fly from some text -func create_resource_from_text(text: String) -> Resource: - var parser: DialogueManagerParser = DialogueManagerParser.new() - parser.parse(text, "") - var results: DialogueManagerParseResult = parser.get_data() - var errors: Array[Dictionary] = parser.get_errors() - parser.free() - - if errors.size() > 0: - printerr(DialogueConstants.translate(&"runtime.errors").format({ count = errors.size() })) - for error in errors: - printerr(DialogueConstants.translate(&"runtime.error_detail").format({ - line = error.line_number + 1, - message = DialogueConstants.get_error_message(error.error) - })) - assert(false, DialogueConstants.translate(&"runtime.errors_see_details").format({ count = errors.size() })) - - var resource: DialogueResource = DialogueResource.new() - resource.using_states = results.using_states - resource.titles = results.titles - resource.first_title = results.first_title - resource.character_names = results.character_names - resource.lines = results.lines - resource.raw_text = text - - return resource - - -## Show the example balloon -func show_example_dialogue_balloon(resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> CanvasLayer: - var balloon: Node = load(_get_example_balloon_path()).instantiate() - get_current_scene.call().add_child(balloon) - balloon.start(resource, title, extra_game_states) - - return balloon - - -## Show the configured dialogue balloon -func show_dialogue_balloon(resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> Node: - var balloon_path: String = DialogueSettings.get_setting(&"balloon_path", _get_example_balloon_path()) - if not ResourceLoader.exists(balloon_path): - balloon_path = _get_example_balloon_path() - return show_dialogue_balloon_scene(balloon_path, resource, title, extra_game_states) - - -## Show a given balloon scene -func show_dialogue_balloon_scene(balloon_scene, resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> Node: - if balloon_scene is String: - balloon_scene = load(balloon_scene) - if balloon_scene is PackedScene: - balloon_scene = balloon_scene.instantiate() - - var balloon: Node = balloon_scene - get_current_scene.call().add_child(balloon) - if balloon.has_method(&"start"): - balloon.start(resource, title, extra_game_states) - elif balloon.has_method(&"Start"): - balloon.Start(resource, title, extra_game_states) - else: - assert(false, DialogueConstants.translate(&"runtime.dialogue_balloon_missing_start_method")) - return balloon - - -# Get the path to the example balloon -func _get_example_balloon_path() -> String: - var is_small_window: bool = ProjectSettings.get_setting("display/window/size/viewport_width") < 400 - var balloon_path: String = "/example_balloon/small_example_balloon.tscn" if is_small_window else "/example_balloon/example_balloon.tscn" - return get_script().resource_path.get_base_dir() + balloon_path - - -### Dotnet bridge - - -func _get_dotnet_dialogue_manager() -> Node: - return load(get_script().resource_path.get_base_dir() + "/DialogueManager.cs").new() - - -func _bridge_get_next_dialogue_line(resource: DialogueResource, key: String, extra_game_states: Array = []) -> void: - # dotnet needs at least one await tick of the signal gets called too quickly - await get_tree().process_frame - - var line = await get_next_dialogue_line(resource, key, extra_game_states) - bridge_get_next_dialogue_line_completed.emit(line) - - -func _bridge_mutate(mutation: Dictionary, extra_game_states: Array, is_inline_mutation: bool = false) -> void: - await mutate(mutation, extra_game_states, is_inline_mutation) - bridge_mutated.emit() - - -### Helpers - - -# Get a line by its ID -func get_line(resource: DialogueResource, key: String, extra_game_states: Array) -> DialogueLine: - key = key.strip_edges() - - # See if we were given a stack instead of just the one key - var stack: Array = key.split("|") - key = stack.pop_front() - var id_trail: String = "" if stack.size() == 0 else "|" + "|".join(stack) - - # Key is blank so just use the first title - if key == null or key == "": - key = resource.first_title - - # See if we just ended the conversation - if key in [DialogueConstants.ID_END, DialogueConstants.ID_NULL, null]: - if stack.size() > 0: - return await get_line(resource, "|".join(stack), extra_game_states) - else: - return null - elif key == DialogueConstants.ID_END_CONVERSATION: - return null - - # See if it is a title - if key.begins_with("~ "): - key = key.substr(2) - if resource.titles.has(key): - key = resource.titles.get(key) - - if key in resource.titles.values(): - passed_title.emit(resource.titles.find_key(key)) - - if not resource.lines.has(key): - assert(false, DialogueConstants.translate(&"errors.key_not_found").format({ key = key })) - - var data: Dictionary = resource.lines.get(key) - - # Check for weighted random lines - if data.has(&"siblings"): - var target_weight: float = randf_range(0, data.siblings.reduce(func(total, sibling): return total + sibling.weight, 0)) - var cummulative_weight: float = 0 - for sibling in data.siblings: - if target_weight < cummulative_weight + sibling.weight: - data = resource.lines.get(sibling.id) - break - else: - cummulative_weight += sibling.weight - - # Check condtiions - if data.type == DialogueConstants.TYPE_CONDITION: - # "else" will have no actual condition - if await check_condition(data, extra_game_states): - return await get_line(resource, data.next_id + id_trail, extra_game_states) - else: - return await get_line(resource, data.next_conditional_id + id_trail, extra_game_states) - - # Evaluate jumps - elif data.type == DialogueConstants.TYPE_GOTO: - if data.is_snippet: - id_trail = "|" + data.next_id_after + id_trail - return await get_line(resource, data.next_id + id_trail, extra_game_states) - - elif data.type == DialogueConstants.TYPE_DIALOGUE: - if not data.has(&"id"): - data.id = key - - # Set up a line object - var line: DialogueLine = await create_dialogue_line(data, extra_game_states) - - # If the jump point somehow has no content then just end - if not line: return null - - # If we are the first of a list of responses then get the other ones - if data.type == DialogueConstants.TYPE_RESPONSE: - # Note: For some reason C# has occasional issues with using the responses property directly - # so instead we use set and get here. - line.set(&"responses", await get_responses(data.get(&"responses", []), resource, id_trail, extra_game_states)) - return line - - # Inject the next node's responses if they have any - if resource.lines.has(line.next_id): - var next_line: Dictionary = resource.lines.get(line.next_id) - - # If the response line is marked as a title then make sure to emit the passed_title signal. - if line.next_id in resource.titles.values(): - passed_title.emit(resource.titles.find_key(line.next_id)) - - # If the next line is a title then check where it points to see if that is a set of responses. - if next_line.type == DialogueConstants.TYPE_GOTO and resource.lines.has(next_line.next_id): - next_line = resource.lines.get(next_line.next_id) - - if next_line != null and next_line.type == DialogueConstants.TYPE_RESPONSE: - # Note: For some reason C# has occasional issues with using the responses property directly - # so instead we use set and get here. - line.set(&"responses", await get_responses(next_line.get(&"responses", []), resource, id_trail, extra_game_states)) - - line.next_id = "|".join(stack) if line.next_id == DialogueConstants.ID_NULL else line.next_id + id_trail - return line - - -# Show a message or crash with error -func show_error_for_missing_state_value(message: String, will_show: bool = true) -> void: - if not will_show: return - - if DialogueSettings.get_setting(&"ignore_missing_state_values", false): - push_error(message) - elif will_show: - # If you're here then you're missing a method or property in your game state. The error - # message down in the debugger will give you some more information. - assert(false, message) - - -# Translate a string -func translate(data: Dictionary) -> String: - if translation_source == TranslationSource.None: - return data.text - - if data.translation_key == "" or data.translation_key == data.text: - return tr(data.text) - else: - # Line IDs work slightly differently depending on whether the translation came from a - # CSV or a PO file. CSVs use the line ID (or the line itself) as the translatable string - # whereas POs use the ID as context and the line itself as the translatable string. - match translation_source: - TranslationSource.PO: - return tr(data.text, StringName(data.translation_key)) - - TranslationSource.CSV: - return tr(data.translation_key) - - TranslationSource.Guess: - var translation_files: Array = ProjectSettings.get_setting(&"internationalization/locale/translations") - if translation_files.filter(func(f: String): return f.get_extension() == &"po").size() > 0: - # Assume PO - return tr(data.text, StringName(data.translation_key)) - else: - # Assume CSV - return tr(data.translation_key) - - return tr(data.translation_key) - - -# Create a line of dialogue -func create_dialogue_line(data: Dictionary, extra_game_states: Array) -> DialogueLine: - match data.type: - DialogueConstants.TYPE_DIALOGUE: - var resolved_data: ResolvedLineData = await get_resolved_line_data(data, extra_game_states) - return DialogueLine.new({ - id = data.get(&"id", ""), - type = DialogueConstants.TYPE_DIALOGUE, - next_id = data.next_id, - character = await get_resolved_character(data, extra_game_states), - character_replacements = data.character_replacements, - text = resolved_data.text, - text_replacements = data.text_replacements, - translation_key = data.translation_key, - pauses = resolved_data.pauses, - speeds = resolved_data.speeds, - inline_mutations = resolved_data.mutations, - time = resolved_data.time, - tags = data.get(&"tags", []), - extra_game_states = extra_game_states - }) - - DialogueConstants.TYPE_RESPONSE: - return DialogueLine.new({ - id = data.get(&"id", ""), - type = DialogueConstants.TYPE_RESPONSE, - next_id = data.next_id, - tags = data.get(&"tags", []), - extra_game_states = extra_game_states - }) - - DialogueConstants.TYPE_MUTATION: - return DialogueLine.new({ - id = data.get(&"id", ""), - type = DialogueConstants.TYPE_MUTATION, - next_id = data.next_id, - mutation = data.mutation, - extra_game_states = extra_game_states - }) - - return null - - -# Create a response -func create_response(data: Dictionary, extra_game_states: Array) -> DialogueResponse: - var resolved_data: ResolvedLineData = await get_resolved_line_data(data, extra_game_states) - return DialogueResponse.new({ - id = data.get(&"id", ""), - type = DialogueConstants.TYPE_RESPONSE, - next_id = data.next_id, - is_allowed = data.is_allowed, - character = await get_resolved_character(data, extra_game_states), - character_replacements = data.get(&"character_replacements", [] as Array[Dictionary]), - text = resolved_data.text, - text_replacements = data.text_replacements, - tags = data.get(&"tags", []), - translation_key = data.translation_key - }) - - -# Get the current game states -func get_game_states(extra_game_states: Array) -> Array: - if not _has_loaded_autoloads: - _has_loaded_autoloads = true - # Add any autoloads to a generic state so we can refer to them by name - for child in get_tree().root.get_children(): - # Ignore the dialogue manager - if child.name == &"DialogueManager": continue - # Ignore the current main scene - if get_tree().current_scene and child.name == get_tree().current_scene.name: continue - # Add the node to our known autoloads - _autoloads[child.name] = child - game_states = [_autoloads] - # Add any other state shortcuts from settings - for node_name in DialogueSettings.get_setting(&"states", []): - var state: Node = get_node_or_null("/root/" + node_name) - if state: - game_states.append(state) - - var current_scene: Node = get_current_scene.call() - var unique_states: Array = [] - for state in extra_game_states + [current_scene] + game_states: - if state != null and not unique_states.has(state): - unique_states.append(state) - return unique_states - - -# Check if a condition is met -func check_condition(data: Dictionary, extra_game_states: Array) -> bool: - if data.get(&"condition", null) == null: return true - if data.condition.size() == 0: return true - - return await resolve(data.condition.expression.duplicate(true), extra_game_states) - - -# Make a change to game state or run a method -func mutate(mutation: Dictionary, extra_game_states: Array, is_inline_mutation: bool = false) -> void: - var expression: Array[Dictionary] = mutation.expression - - # Handle built in mutations - if expression[0].type == DialogueConstants.TOKEN_FUNCTION and expression[0].function in [&"wait", &"debug"]: - var args: Array = await resolve_each(expression[0].value, extra_game_states) - match expression[0].function: - &"wait": - mutated.emit(mutation) - await get_tree().create_timer(float(args[0])).timeout - return - - &"debug": - prints("Debug:", args) - await get_tree().process_frame - - # Or pass through to the resolver - else: - if not mutation_contains_assignment(mutation.expression) and not is_inline_mutation: - mutated.emit(mutation) - - if mutation.get("is_blocking", true): - await resolve(mutation.expression.duplicate(true), extra_game_states) - return - else: - resolve(mutation.expression.duplicate(true), extra_game_states) - - # Wait one frame to give the dialogue handler a chance to yield - await get_tree().process_frame - - -func mutation_contains_assignment(mutation: Array) -> bool: - for token in mutation: - if token.type == DialogueConstants.TOKEN_ASSIGNMENT: - return true - return false - - -func resolve_each(array: Array, extra_game_states: Array) -> Array: - var results: Array = [] - for item in array: - results.append(await resolve(item.duplicate(true), extra_game_states)) - return results - - -# Replace an array of line IDs with their response prompts -func get_responses(ids: Array, resource: DialogueResource, id_trail: String, extra_game_states: Array) -> Array[DialogueResponse]: - var responses: Array[DialogueResponse] = [] - for id in ids: - var data: Dictionary = resource.lines.get(id).duplicate(true) - data.is_allowed = await check_condition(data, extra_game_states) - if DialogueSettings.get_setting(&"include_all_responses", false) or data.is_allowed: - var response: DialogueResponse = await create_response(data, extra_game_states) - response.next_id += id_trail - responses.append(response) - - return responses - - -# Get a value on the current scene or game state -func get_state_value(property: String, extra_game_states: Array): - # Special case for static primitive calls - if property == "Color": - return Color() - elif property == "Vector2": - return Vector2.ZERO - elif property == "Vector3": - return Vector3.ZERO - elif property == "Vector4": - return Vector4.ZERO - elif property == "Quaternian": - return Quaternion() - - var expression = Expression.new() - if expression.parse(property) != OK: - assert(false, DialogueConstants.translate(&"runtime.invalid_expression").format({ expression = property, error = expression.get_error_text() })) - - for state in get_game_states(extra_game_states): - if typeof(state) == TYPE_DICTIONARY: - if state.has(property): - return state.get(property) - else: - var result = expression.execute([], state, false) - if not expression.has_execute_failed(): - return result - - if include_singletons and Engine.has_singleton(property): - return Engine.get_singleton(property) - - if include_classes: - for class_data in ProjectSettings.get_global_class_list(): - if class_data.get(&"class") == property: - return load(class_data.path).new() - - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found").format({ property = property, states = str(get_game_states(extra_game_states)) })) - - -# Set a value on the current scene or game state -func set_state_value(property: String, value, extra_game_states: Array) -> void: - for state in get_game_states(extra_game_states): - if typeof(state) == TYPE_DICTIONARY: - if state.has(property): - state[property] = value - return - elif thing_has_property(state, property): - state.set(property, value) - return - - if property.to_snake_case() != property: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found_missing_export").format({ property = property, states = str(get_game_states(extra_game_states)) })) - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found").format({ property = property, states = str(get_game_states(extra_game_states)) })) - - -# Collapse any expressions -func resolve(tokens: Array, extra_game_states: Array): - # Handle groups first - for token in tokens: - if token.type == DialogueConstants.TOKEN_GROUP: - token["type"] = "value" - token["value"] = await resolve(token.value, extra_game_states) - - # Then variables/methods - var i: int = 0 - var limit: int = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - - if token.type == DialogueConstants.TOKEN_FUNCTION: - var function_name: String = token.function - var args = await resolve_each(token.value, extra_game_states) - if tokens[i - 1].type == DialogueConstants.TOKEN_DOT: - # If we are calling a deeper function then we need to collapse the - # value into the thing we are calling the function on - var caller: Dictionary = tokens[i - 2] - if Builtins.is_supported(caller.value): - caller["type"] = "value" - caller["value"] = Builtins.resolve_method(caller.value, function_name, args) - tokens.remove_at(i) - tokens.remove_at(i-1) - i -= 2 - elif thing_has_method(caller.value, function_name, args): - caller["type"] = "value" - caller["value"] = await resolve_thing_method(caller.value, function_name, args) - tokens.remove_at(i) - tokens.remove_at(i-1) - i -= 2 - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.method_not_callable").format({ method = function_name, object = str(caller.value) })) - else: - var found: bool = false - match function_name: - &"str": - token["type"] = "value" - token["value"] = str(args[0]) - found = true - &"Vector2": - token["type"] = "value" - token["value"] = Vector2(args[0], args[1]) - found = true - &"Vector2i": - token["type"] = "value" - token["value"] = Vector2i(args[0], args[1]) - found = true - &"Vector3": - token["type"] = "value" - token["value"] = Vector3(args[0], args[1], args[2]) - found = true - &"Vector3i": - token["type"] = "value" - token["value"] = Vector3i(args[0], args[1], args[2]) - found = true - &"Vector4": - token["type"] = "value" - token["value"] = Vector4(args[0], args[1], args[2], args[3]) - found = true - &"Vector4i": - token["type"] = "value" - token["value"] = Vector4i(args[0], args[1], args[2], args[3]) - found = true - &"Quaternion": - token["type"] = "value" - token["value"] = Quaternion(args[0], args[1], args[2], args[3]) - found = true - &"Color": - token["type"] = "value" - match args.size(): - 0: - token["value"] = Color() - 1: - token["value"] = Color(args[0]) - 2: - token["value"] = Color(args[0], args[1]) - 3: - token["value"] = Color(args[0], args[1], args[2]) - 4: - token["value"] = Color(args[0], args[1], args[2], args[3]) - found = true - &"load": - token["type"] = "value" - token["value"] = load(args[0]) - found = true - &"emit": - token["type"] = "value" - token["value"] = resolve_signal(args, extra_game_states) - found = true - _: - for state in get_game_states(extra_game_states): - if thing_has_method(state, function_name, args): - token["type"] = "value" - token["value"] = await resolve_thing_method(state, function_name, args) - found = true - break - - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.method_not_found").format({ - method = args[0] if function_name in ["call", "call_deferred"] else function_name, - states = str(get_game_states(extra_game_states)) - }), not found) - - elif token.type == DialogueConstants.TOKEN_DICTIONARY_REFERENCE: - var value - if i > 0 and tokens[i - 1].type == DialogueConstants.TOKEN_DOT: - # If we are deep referencing then we need to get the parent object. - # `parent.value` is the actual object and `token.variable` is the name of - # the property within it. - value = tokens[i - 2].value[token.variable] - # Clean up the previous tokens - token.erase("variable") - tokens.remove_at(i - 1) - tokens.remove_at(i - 2) - i -= 2 - else: - # Otherwise we can just get this variable as a normal state reference - value = get_state_value(token.variable, extra_game_states) - - var index = await resolve(token.value, extra_game_states) - if typeof(value) == TYPE_DICTIONARY: - if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # If the next token is an assignment then we need to leave this as a reference - # so that it can be resolved once everything ahead of it has been resolved - token["type"] = "dictionary" - token["value"] = value - token["key"] = index - else: - if value.has(index): - token["type"] = "value" - token["value"] = value[index] - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.key_not_found").format({ key = str(index), dictionary = token.variable })) - elif typeof(value) == TYPE_ARRAY: - if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # If the next token is an assignment then we need to leave this as a reference - # so that it can be resolved once everything ahead of it has been resolved - token["type"] = "array" - token["value"] = value - token["key"] = index - else: - if index >= 0 and index < value.size(): - token["type"] = "value" - token["value"] = value[index] - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = index, array = token.variable })) - - elif token.type == DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE: - var dictionary: Dictionary = tokens[i - 1] - var index = await resolve(token.value, extra_game_states) - var value = dictionary.value - if typeof(value) == TYPE_DICTIONARY: - if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # If the next token is an assignment then we need to leave this as a reference - # so that it can be resolved once everything ahead of it has been resolved - dictionary["type"] = "dictionary" - dictionary["key"] = index - dictionary["value"] = value - tokens.remove_at(i) - i -= 1 - else: - if dictionary.value.has(index): - dictionary["value"] = value.get(index) - tokens.remove_at(i) - i -= 1 - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.key_not_found").format({ key = str(index), dictionary = value })) - elif typeof(value) == TYPE_ARRAY: - if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # If the next token is an assignment then we need to leave this as a reference - # so that it can be resolved once everything ahead of it has been resolved - dictionary["type"] = "array" - dictionary["value"] = value - dictionary["key"] = index - tokens.remove_at(i) - i -= 1 - else: - if index >= 0 and index < value.size(): - dictionary["value"] = value[index] - tokens.remove_at(i) - i -= 1 - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = index, array = value })) - - elif token.type == DialogueConstants.TOKEN_ARRAY: - token["type"] = "value" - token["value"] = await resolve_each(token.value, extra_game_states) - - elif token.type == DialogueConstants.TOKEN_DICTIONARY: - token["type"] = "value" - var dictionary = {} - for key in token.value.keys(): - var resolved_key = await resolve([key], extra_game_states) - var preresolved_value = token.value.get(key) - if typeof(preresolved_value) != TYPE_ARRAY: - preresolved_value = [preresolved_value] - var resolved_value = await resolve(preresolved_value, extra_game_states) - dictionary[resolved_key] = resolved_value - token["value"] = dictionary - - elif token.type == DialogueConstants.TOKEN_VARIABLE or token.type == DialogueConstants.TOKEN_NUMBER: - if str(token.value) == "null": - token["type"] = "value" - token["value"] = null - elif tokens[i - 1].type == DialogueConstants.TOKEN_DOT: - var caller: Dictionary = tokens[i - 2] - var property = token.value - if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # If the next token is an assignment then we need to leave this as a reference - # so that it can be resolved once everything ahead of it has been resolved - caller["type"] = "property" - caller["property"] = property - else: - # If we are requesting a deeper property then we need to collapse the - # value into the thing we are referencing from - caller["type"] = "value" - if Builtins.is_supported(caller.value): - caller["value"] = Builtins.resolve_property(caller.value, property) - else: - caller["value"] = caller.value.get(property) - tokens.remove_at(i) - tokens.remove_at(i-1) - i -= 2 - elif tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # It's a normal variable but we will be assigning to it so don't resolve - # it until everything after it has been resolved - token["type"] = "variable" - else: - token["type"] = "value" - token["value"] = get_state_value(str(token.value), extra_game_states) - - i += 1 - - # Then multiply and divide - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_OPERATOR and token.value in ["*", "/", "%"]: - token["type"] = "value" - token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) - tokens.remove_at(i+1) - tokens.remove_at(i-1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - # Then addition and subtraction - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_OPERATOR and token.value in ["+", "-"]: - token["type"] = "value" - token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) - tokens.remove_at(i+1) - tokens.remove_at(i-1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - # Then negations - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_NOT: - token["type"] = "value" - token["value"] = not tokens[i+1].value - tokens.remove_at(i+1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - # Then comparisons - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_COMPARISON: - token["type"] = "value" - token["value"] = compare(token.value, tokens[i-1].value, tokens[i+1].value) - tokens.remove_at(i+1) - tokens.remove_at(i-1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - # Then and/or - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_AND_OR: - token["type"] = "value" - token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) - tokens.remove_at(i+1) - tokens.remove_at(i-1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - # Lastly, resolve any assignments - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_ASSIGNMENT: - var lhs: Dictionary = tokens[i - 1] - var value - - match lhs.type: - &"variable": - value = apply_operation(token.value, get_state_value(lhs.value, extra_game_states), tokens[i+1].value) - set_state_value(lhs.value, value, extra_game_states) - &"property": - value = apply_operation(token.value, lhs.value.get(lhs.property), tokens[i+1].value) - if typeof(lhs.value) == TYPE_DICTIONARY: - lhs.value[lhs.property] = value - else: - lhs.value.set(lhs.property, value) - &"dictionary": - value = apply_operation(token.value, lhs.value.get(lhs.key, null), tokens[i+1].value) - lhs.value[lhs.key] = value - &"array": - show_error_for_missing_state_value( - DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = lhs.key, array = lhs.value }), - lhs.key >= lhs.value.size() - ) - value = apply_operation(token.value, lhs.value[lhs.key], tokens[i+1].value) - lhs.value[lhs.key] = value - _: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.left_hand_size_cannot_be_assigned_to")) - - token["type"] = "value" - token["value"] = value - tokens.remove_at(i+1) - tokens.remove_at(i-1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - return tokens[0].value - - -func compare(operator: String, first_value, second_value) -> bool: - match operator: - &"in": - if first_value == null or second_value == null: - return false - else: - return first_value in second_value - &"<": - if first_value == null: - return true - elif second_value == null: - return false - else: - return first_value < second_value - &">": - if first_value == null: - return false - elif second_value == null: - return true - else: - return first_value > second_value - &"<=": - if first_value == null: - return true - elif second_value == null: - return false - else: - return first_value <= second_value - &">=": - if first_value == null: - return false - elif second_value == null: - return true - else: - return first_value >= second_value - &"==": - if first_value == null: - if typeof(second_value) == TYPE_BOOL: - return second_value == false - else: - return second_value == null - else: - return first_value == second_value - &"!=": - if first_value == null: - if typeof(second_value) == TYPE_BOOL: - return second_value == true - else: - return second_value != null - else: - return first_value != second_value - - return false - - -func apply_operation(operator: String, first_value, second_value): - match operator: - &"=": - return second_value - &"+", &"+=": - return first_value + second_value - &"-", &"-=": - return first_value - second_value - &"/", &"/=": - return first_value / second_value - &"*", &"*=": - return first_value * second_value - &"%": - return first_value % second_value - &"and": - return first_value and second_value - &"or": - return first_value or second_value - - assert(false, DialogueConstants.translate(&"runtime.unknown_operator")) - - -# Check if a dialogue line contains meaningful information -func is_valid(line: DialogueLine) -> bool: - if line == null: - return false - if line.type == DialogueConstants.TYPE_MUTATION and line.mutation == null: - return false - if line.type == DialogueConstants.TYPE_RESPONSE and line.get(&"responses").size() == 0: - return false - return true - - -func thing_has_method(thing, method: String, args: Array) -> bool: - if Builtins.is_supported(thing): - return thing != _autoloads - - if method in [&"call", &"call_deferred"]: - return thing.has_method(args[0]) - - if method == &"emit_signal": - return thing.has_signal(args[0]) - - if thing.has_method(method): - return true - - if method.to_snake_case() != method and DialogueSettings.has_dotnet_solution(): - # If we get this far then the method might be a C# method with a Task return type - return _get_dotnet_dialogue_manager().ThingHasMethod(thing, method) - - return false - - -# Check if a given property exists -func thing_has_property(thing: Object, property: String) -> bool: - if thing == null: - return false - - for p in thing.get_property_list(): - if _node_properties.has(p.name): - # Ignore any properties on the base Node - continue - if p.name == property: - return true - - return false - - -func resolve_signal(args: Array, extra_game_states: Array): - if args[0] is Signal: - args[0] = args[0].get_name() - - for state in get_game_states(extra_game_states): - if typeof(state) == TYPE_DICTIONARY: - continue - elif state.has_signal(args[0]): - match args.size(): - 1: - state.emit_signal(args[0]) - 2: - state.emit_signal(args[0], args[1]) - 3: - state.emit_signal(args[0], args[1], args[2]) - 4: - state.emit_signal(args[0], args[1], args[2], args[3]) - 5: - state.emit_signal(args[0], args[1], args[2], args[3], args[4]) - 6: - state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5]) - 7: - state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5], args[6]) - 8: - state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]) - return - - # The signal hasn't been found anywhere - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.signal_not_found").format({ signal_name = args[0], states = str(get_game_states(extra_game_states)) })) - - -func resolve_thing_method(thing, method: String, args: Array): - if Builtins.is_supported(thing): - var result = Builtins.resolve_method(thing, method, args) - if not Builtins.has_resolve_method_failed(): - return result - - if thing.has_method(method): - # Try to convert any literals to the right type - var method_info: Dictionary = thing.get_method_list().filter(func(m): return method == m.name)[0] - var method_args: Array = method_info.args - if method_info.flags & METHOD_FLAG_VARARG == 0 and method_args.size() < args.size(): - assert(false, DialogueConstants.translate(&"runtime.expected_n_got_n_args").format({ expected = method_args.size(), method = method, received = args.size()})) - for i in range(0, args.size()): - var m: Dictionary = method_args[i] - var to_type:int = typeof(args[i]) - if m.type == TYPE_ARRAY: - match m.hint_string: - &"String": - to_type = TYPE_PACKED_STRING_ARRAY - &"int": - to_type = TYPE_PACKED_INT64_ARRAY - &"float": - to_type = TYPE_PACKED_FLOAT64_ARRAY - &"Vector2": - to_type = TYPE_PACKED_VECTOR2_ARRAY - &"Vector3": - to_type = TYPE_PACKED_VECTOR3_ARRAY - _: - if m.hint_string != "": - assert(false, DialogueConstants.translate(&"runtime.unsupported_array_type").format({ type = m.hint_string})) - if typeof(args[i]) != to_type: - args[i] = convert(args[i], to_type) - - return await thing.callv(method, args) - - # If we get here then it's probably a C# method with a Task return type - var dotnet_dialogue_manager = _get_dotnet_dialogue_manager() - dotnet_dialogue_manager.ResolveThingMethod(thing, method, args) - return await dotnet_dialogue_manager.Resolved diff --git a/addons/dialogue_manager/dialogue_reponses_menu.gd b/addons/dialogue_manager/dialogue_reponses_menu.gd deleted file mode 100644 index 6da0e5c..0000000 --- a/addons/dialogue_manager/dialogue_reponses_menu.gd +++ /dev/null @@ -1,131 +0,0 @@ -@icon("./assets/responses_menu.svg") - -## A VBoxContainer for dialogue responses provided by [b]Dialogue Manager[/b]. -class_name DialogueResponsesMenu extends VBoxContainer - - -## Emitted when a response is selected. -signal response_selected(response) - - -## Optionally specify a control to duplicate for each response -@export var response_template: Control - -## The action for accepting a response (is possibly overridden by parent dialogue balloon). -@export var next_action: StringName = &"" - -# The list of dialogue responses. -var responses: Array = []: - set(value): - responses = value - - # Remove any current items - for item in get_children(): - if item == response_template: continue - - remove_child(item) - item.queue_free() - - # Add new items - if responses.size() > 0: - for response in responses: - var item: Control - if is_instance_valid(response_template): - item = response_template.duplicate(DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_SIGNALS) - item.show() - else: - item = Button.new() - item.name = "Response%d" % get_child_count() - if not response.is_allowed: - item.name = String(item.name) + "Disallowed" - item.disabled = true - - # If the item has a response property then use that - if "response" in item: - item.response = response - # Otherwise assume we can just set the text - else: - item.text = response.text - - item.set_meta("response", response) - - add_child(item) - - _configure_focus() - - -func _ready() -> void: - visibility_changed.connect(func(): - if visible and get_menu_items().size() > 0: - get_menu_items()[0].grab_focus() - ) - - if is_instance_valid(response_template): - response_template.hide() - - -# This is deprecated. -func set_responses(next_responses: Array) -> void: - self.responses = next_responses - - -# Prepare the menu for keyboard and mouse navigation. -func _configure_focus() -> void: - var items = get_menu_items() - for i in items.size(): - var item: Control = items[i] - - item.focus_mode = Control.FOCUS_ALL - - item.focus_neighbor_left = item.get_path() - item.focus_neighbor_right = item.get_path() - - if i == 0: - item.focus_neighbor_top = item.get_path() - item.focus_previous = item.get_path() - else: - item.focus_neighbor_top = items[i - 1].get_path() - item.focus_previous = items[i - 1].get_path() - - if i == items.size() - 1: - item.focus_neighbor_bottom = item.get_path() - item.focus_next = item.get_path() - else: - item.focus_neighbor_bottom = items[i + 1].get_path() - item.focus_next = items[i + 1].get_path() - - item.mouse_entered.connect(_on_response_mouse_entered.bind(item)) - item.gui_input.connect(_on_response_gui_input.bind(item, item.get_meta("response"))) - - items[0].grab_focus() - - -## Get the selectable items in the menu. -func get_menu_items() -> Array: - var items: Array = [] - for child in get_children(): - if not child.visible: continue - if "Disallowed" in child.name: continue - items.append(child) - - return items - - -### Signals - - -func _on_response_mouse_entered(item: Control) -> void: - if "Disallowed" in item.name: return - - item.grab_focus() - - -func _on_response_gui_input(event: InputEvent, item: Control, response) -> void: - if "Disallowed" in item.name: return - - get_viewport().set_input_as_handled() - - if event is InputEventMouseButton and event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT: - response_selected.emit(response) - elif event.is_action_pressed(&"ui_accept" if next_action.is_empty() else next_action) and item in get_menu_items(): - response_selected.emit(response) diff --git a/addons/dialogue_manager/dialogue_resource.gd b/addons/dialogue_manager/dialogue_resource.gd deleted file mode 100644 index a406560..0000000 --- a/addons/dialogue_manager/dialogue_resource.gd +++ /dev/null @@ -1,42 +0,0 @@ -@tool -@icon("./assets/icon.svg") - -## A collection of dialogue lines for use with [code]DialogueManager[/code]. -class_name DialogueResource extends Resource - - -const _DialogueManager = preload("./dialogue_manager.gd") - -## A list of state shortcuts -@export var using_states: PackedStringArray = [] - -## A map of titles and the lines they point to. -@export var titles: Dictionary = {} - -## A list of character names. -@export var character_names: PackedStringArray = [] - -## The first title in the file. -@export var first_title: String = "" - -## A map of the encoded lines of dialogue. -@export var lines: Dictionary = {} - -## raw version of the text -@export var raw_text: String - - -## Get the next printable line of dialogue, starting from a referenced line ([code]title[/code] can -## be a title string or a stringified line number). Runs any mutations along the way and then returns -## the first dialogue line encountered. -func get_next_dialogue_line(title: String, extra_game_states: Array = [], mutation_behaviour: _DialogueManager.MutationBehaviour = _DialogueManager.MutationBehaviour.Wait) -> DialogueLine: - return await Engine.get_singleton("DialogueManager").get_next_dialogue_line(self, title, extra_game_states, mutation_behaviour) - - -## Get the list of any titles found in the file. -func get_titles() -> PackedStringArray: - return titles.keys() - - -func _to_string() -> String: - return "<DialogueResource titles=\"%s\">" % [",".join(titles.keys())] diff --git a/addons/dialogue_manager/dialogue_response.gd b/addons/dialogue_manager/dialogue_response.gd deleted file mode 100644 index 92cec24..0000000 --- a/addons/dialogue_manager/dialogue_response.gd +++ /dev/null @@ -1,62 +0,0 @@ -## A response to a line of dialogue, usualy attached to a [code]DialogueLine[/code]. -class_name DialogueResponse extends RefCounted - - -const _DialogueConstants = preload("./constants.gd") - - -## The ID of this response -var id: String - -## The internal type of this dialogue object, always set to [code]TYPE_RESPONSE[/code]. -var type: String = _DialogueConstants.TYPE_RESPONSE - -## The next line ID to use if this response is selected by the player. -var next_id: String = "" - -## [code]true[/code] if the condition of this line was met. -var is_allowed: bool = true - -## A character (depending on the "characters in responses" behaviour setting). -var character: String = "" - -## A dictionary of varialbe replaces for the character name. Generally for internal use only. -var character_replacements: Array[Dictionary] = [] - -## The prompt for this response. -var text: String = "" - -## A dictionary of variable replaces for the text. Generally for internal use only. -var text_replacements: Array[Dictionary] = [] - -## Any #tags -var tags: PackedStringArray = [] - -## The key to use for translating the text. -var translation_key: String = "" - - -func _init(data: Dictionary = {}) -> void: - if data.size() > 0: - id = data.id - type = data.type - next_id = data.next_id - is_allowed = data.is_allowed - character = data.character - character_replacements = data.character_replacements - text = data.text - text_replacements = data.text_replacements - tags = data.tags - translation_key = data.translation_key - - -func _to_string() -> String: - return "<DialogueResponse text=\"%s\">" % text - - -func get_tag_value(tag_name: String) -> String: - var wrapped := "%s=" % tag_name - for t in tags: - if t.begins_with(wrapped): - return t.replace(wrapped, "").strip_edges() - return "" diff --git a/addons/dialogue_manager/editor_translation_parser_plugin.gd b/addons/dialogue_manager/editor_translation_parser_plugin.gd deleted file mode 100644 index 9d404e2..0000000 --- a/addons/dialogue_manager/editor_translation_parser_plugin.gd +++ /dev/null @@ -1,43 +0,0 @@ -extends EditorTranslationParserPlugin - - -const DialogueConstants = preload("./constants.gd") -const DialogueSettings = preload("./settings.gd") -const DialogueManagerParseResult = preload("./components/parse_result.gd") - - -func _parse_file(path: String, msgids: Array, msgids_context_plural: Array) -> void: - var file: FileAccess = FileAccess.open(path, FileAccess.READ) - var text: String = file.get_as_text() - - var data: DialogueManagerParseResult = DialogueManagerParser.parse_string(text, path) - var known_keys: PackedStringArray = PackedStringArray([]) - - # Add all character names if settings ask for it - if DialogueSettings.get_setting("export_characters_in_translation", true): - var character_names: PackedStringArray = data.character_names - for character_name in character_names: - if character_name in known_keys: continue - - known_keys.append(character_name) - - msgids_context_plural.append([character_name.replace('"', '\\"'), "dialogue", ""]) - - # Add all dialogue lines and responses - var dialogue: Dictionary = data.lines - for key in dialogue.keys(): - var line: Dictionary = dialogue.get(key) - - if not line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: continue - if line.translation_key in known_keys: continue - - known_keys.append(line.translation_key) - - if line.translation_key == "" or line.translation_key == line.text: - msgids_context_plural.append([line.text.replace('"', '\\"'), "", ""]) - else: - msgids_context_plural.append([line.text.replace('"', '\\"'), line.translation_key.replace('"', '\\"'), ""]) - - -func _get_recognized_extensions() -> PackedStringArray: - return ["dialogue"] diff --git a/addons/dialogue_manager/example_balloon/ExampleBalloon.cs b/addons/dialogue_manager/example_balloon/ExampleBalloon.cs deleted file mode 100644 index a6574e0..0000000 --- a/addons/dialogue_manager/example_balloon/ExampleBalloon.cs +++ /dev/null @@ -1,204 +0,0 @@ -using Godot; -using Godot.Collections; - -namespace DialogueManagerRuntime -{ - public partial class ExampleBalloon : CanvasLayer - { - [Export] public string NextAction = "ui_accept"; - [Export] public string SkipAction = "ui_cancel"; - - - Control balloon; - RichTextLabel characterLabel; - RichTextLabel dialogueLabel; - VBoxContainer responsesMenu; - - Resource resource; - Array<Variant> temporaryGameStates = new Array<Variant>(); - bool isWaitingForInput = false; - bool willHideBalloon = false; - - DialogueLine dialogueLine; - DialogueLine DialogueLine - { - get => dialogueLine; - set - { - isWaitingForInput = false; - balloon.FocusMode = Control.FocusModeEnum.All; - balloon.GrabFocus(); - - if (value == null) - { - QueueFree(); - return; - } - - dialogueLine = value; - UpdateDialogue(); - } - } - - - public override void _Ready() - { - balloon = GetNode<Control>("%Balloon"); - characterLabel = GetNode<RichTextLabel>("%CharacterLabel"); - dialogueLabel = GetNode<RichTextLabel>("%DialogueLabel"); - responsesMenu = GetNode<VBoxContainer>("%ResponsesMenu"); - - balloon.Hide(); - - balloon.GuiInput += (@event) => - { - if ((bool)dialogueLabel.Get("is_typing")) - { - bool mouseWasClicked = @event is InputEventMouseButton && (@event as InputEventMouseButton).ButtonIndex == MouseButton.Left && @event.IsPressed(); - bool skipButtonWasPressed = @event.IsActionPressed(SkipAction); - if (mouseWasClicked || skipButtonWasPressed) - { - GetViewport().SetInputAsHandled(); - dialogueLabel.Call("skip_typing"); - return; - } - } - - if (!isWaitingForInput) return; - if (dialogueLine.Responses.Count > 0) return; - - GetViewport().SetInputAsHandled(); - - if (@event is InputEventMouseButton && @event.IsPressed() && (@event as InputEventMouseButton).ButtonIndex == MouseButton.Left) - { - Next(dialogueLine.NextId); - } - else if (@event.IsActionPressed(NextAction) && GetViewport().GuiGetFocusOwner() == balloon) - { - Next(dialogueLine.NextId); - } - }; - - if (string.IsNullOrEmpty((string)responsesMenu.Get("next_action"))) - { - responsesMenu.Set("next_action", NextAction); - } - responsesMenu.Connect("response_selected", Callable.From((DialogueResponse response) => - { - Next(response.NextId); - })); - - DialogueManager.Mutated += OnMutated; - } - - - public override void _ExitTree() - { - DialogueManager.Mutated -= OnMutated; - } - - - public override void _UnhandledInput(InputEvent @event) - { - // Only the balloon is allowed to handle input while it's showing - GetViewport().SetInputAsHandled(); - } - - - public async void Start(Resource dialogueResource, string title, Array<Variant> extraGameStates = null) - { - temporaryGameStates = extraGameStates ?? new Array<Variant>(); - isWaitingForInput = false; - resource = dialogueResource; - - DialogueLine = await DialogueManager.GetNextDialogueLine(resource, title, temporaryGameStates); - } - - - public async void Next(string nextId) - { - DialogueLine = await DialogueManager.GetNextDialogueLine(resource, nextId, temporaryGameStates); - } - - - #region Helpers - - - private async void UpdateDialogue() - { - if (!IsNodeReady()) - { - await ToSignal(this, SignalName.Ready); - } - - // Set up the character name - characterLabel.Visible = !string.IsNullOrEmpty(dialogueLine.Character); - characterLabel.Text = Tr(dialogueLine.Character, "dialogue"); - - // Set up the dialogue - dialogueLabel.Hide(); - dialogueLabel.Set("dialogue_line", dialogueLine); - - // Set up the responses - responsesMenu.Hide(); - responsesMenu.Set("responses", dialogueLine.Responses); - - // Type out the text - balloon.Show(); - willHideBalloon = false; - dialogueLabel.Show(); - if (!string.IsNullOrEmpty(dialogueLine.Text)) - { - dialogueLabel.Call("type_out"); - await ToSignal(dialogueLabel, "finished_typing"); - } - - // Wait for input - if (dialogueLine.Responses.Count > 0) - { - balloon.FocusMode = Control.FocusModeEnum.None; - responsesMenu.Show(); - } - else if (!string.IsNullOrEmpty(dialogueLine.Time)) - { - float time = 0f; - if (!float.TryParse(dialogueLine.Time, out time)) - { - time = dialogueLine.Text.Length * 0.02f; - } - await ToSignal(GetTree().CreateTimer(time), "timeout"); - Next(dialogueLine.NextId); - } - else - { - isWaitingForInput = true; - balloon.FocusMode = Control.FocusModeEnum.All; - balloon.GrabFocus(); - } - } - - - #endregion - - - #region signals - - - private void OnMutated(Dictionary _mutation) - { - isWaitingForInput = false; - willHideBalloon = true; - GetTree().CreateTimer(0.1f).Timeout += () => - { - if (willHideBalloon) - { - willHideBalloon = false; - balloon.Hide(); - } - }; - } - - - #endregion - } -} \ No newline at end of file diff --git a/addons/dialogue_manager/example_balloon/example_balloon.gd b/addons/dialogue_manager/example_balloon/example_balloon.gd deleted file mode 100644 index 875e52f..0000000 --- a/addons/dialogue_manager/example_balloon/example_balloon.gd +++ /dev/null @@ -1,141 +0,0 @@ -extends CanvasLayer - -## 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" - -@onready var balloon: Control = %Balloon -@onready var character_label: RichTextLabel = %CharacterLabel -@onready var dialogue_label: DialogueLabel = %DialogueLabel -@onready var responses_menu: DialogueResponsesMenu = %ResponsesMenu - -## 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 - -## The current line -var dialogue_line: DialogueLine: - set(next_dialogue_line): - is_waiting_for_input = false - balloon.focus_mode = Control.FOCUS_ALL - balloon.grab_focus() - - # The dialogue has finished so close the balloon - if not next_dialogue_line: - queue_free() - return - - # If the node isn't ready yet then none of the labels will be ready yet either - if not is_node_ready(): - await ready - - dialogue_line = next_dialogue_line - - 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.set_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() - get: - return dialogue_line - - -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 - - -func _unhandled_input(_event: InputEvent) -> void: - # Only the balloon is allowed to handle input while it's showing - get_viewport().set_input_as_handled() - - -## 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) - - -## 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) - - -### Signals - - -func _on_mutated(_mutation: Dictionary) -> void: - is_waiting_for_input = false - will_hide_balloon = true - get_tree().create_timer(0.1).timeout.connect(func(): - if will_hide_balloon: - will_hide_balloon = false - balloon.hide() - ) - - -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 _on_responses_menu_response_selected(response: DialogueResponse) -> void: - next(response.next_id) diff --git a/addons/dialogue_manager/example_balloon/example_balloon.tscn b/addons/dialogue_manager/example_balloon/example_balloon.tscn deleted file mode 100644 index 6facc26..0000000 --- a/addons/dialogue_manager/example_balloon/example_balloon.tscn +++ /dev/null @@ -1,149 +0,0 @@ -[gd_scene load_steps=9 format=3 uid="uid://73jm5qjy52vq"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/example_balloon/example_balloon.gd" id="1_36de5"] -[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_a8ve6"] -[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_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="ExampleBalloon" type="CanvasLayer"] -layer = 100 -script = ExtResource("1_36de5") - -[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="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("2_a8ve6")] -unique_name_in_owner = true -layout_mode = 2 -size_flags_vertical = 3 -text = "Dialogue..." - -[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" - -[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"] diff --git a/addons/dialogue_manager/example_balloon/small_example_balloon.tscn b/addons/dialogue_manager/example_balloon/small_example_balloon.tscn deleted file mode 100644 index 3011833..0000000 --- a/addons/dialogue_manager/example_balloon/small_example_balloon.tscn +++ /dev/null @@ -1,173 +0,0 @@ -[gd_scene load_steps=10 format=3 uid="uid://13s5spsk34qu"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/example_balloon/example_balloon.gd" id="1_s2gbs"] -[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_hfvdi"] -[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_menu.gd" id="3_1j1j0"] - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_235ry"] -content_margin_left = 6.0 -content_margin_top = 3.0 -content_margin_right = 6.0 -content_margin_bottom = 3.0 -bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) -border_width_left = 1 -border_width_top = 1 -border_width_right = 1 -border_width_bottom = 1 -border_color = Color(0.345098, 0.345098, 0.345098, 1) -corner_radius_top_left = 3 -corner_radius_top_right = 3 -corner_radius_bottom_right = 3 -corner_radius_bottom_left = 3 - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ufjut"] -content_margin_left = 6.0 -content_margin_top = 3.0 -content_margin_right = 6.0 -content_margin_bottom = 3.0 -bg_color = Color(0.227451, 0.227451, 0.227451, 1) -border_width_left = 1 -border_width_top = 1 -border_width_right = 1 -border_width_bottom = 1 -border_color = Color(1, 1, 1, 1) -corner_radius_top_left = 3 -corner_radius_top_right = 3 -corner_radius_bottom_right = 3 -corner_radius_bottom_left = 3 - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fcbqo"] -content_margin_left = 6.0 -content_margin_top = 3.0 -content_margin_right = 6.0 -content_margin_bottom = 3.0 -bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) -border_width_left = 1 -border_width_top = 1 -border_width_right = 1 -border_width_bottom = 1 -corner_radius_top_left = 3 -corner_radius_top_right = 3 -corner_radius_bottom_right = 3 -corner_radius_bottom_left = 3 - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_t6i7a"] -content_margin_left = 6.0 -content_margin_top = 3.0 -content_margin_right = 6.0 -content_margin_bottom = 3.0 -bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) -border_width_left = 1 -border_width_top = 1 -border_width_right = 1 -border_width_bottom = 1 -corner_radius_top_left = 3 -corner_radius_top_right = 3 -corner_radius_bottom_right = 3 -corner_radius_bottom_left = 3 - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uy0d5"] -bg_color = Color(0, 0, 0, 1) -border_width_left = 1 -border_width_top = 1 -border_width_right = 1 -border_width_bottom = 1 -corner_radius_top_left = 3 -corner_radius_top_right = 3 -corner_radius_bottom_right = 3 -corner_radius_bottom_left = 3 - -[sub_resource type="Theme" id="Theme_qq3yp"] -default_font_size = 8 -Button/styles/disabled = SubResource("StyleBoxFlat_235ry") -Button/styles/focus = SubResource("StyleBoxFlat_ufjut") -Button/styles/hover = SubResource("StyleBoxFlat_fcbqo") -Button/styles/normal = SubResource("StyleBoxFlat_t6i7a") -MarginContainer/constants/margin_bottom = 4 -MarginContainer/constants/margin_left = 8 -MarginContainer/constants/margin_right = 8 -MarginContainer/constants/margin_top = 4 -Panel/styles/panel = SubResource("StyleBoxFlat_uy0d5") - -[node name="ExampleBalloon" type="CanvasLayer"] -layer = 100 -script = ExtResource("1_s2gbs") - -[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"] -layout_mode = 1 -anchors_preset = 12 -anchor_top = 1.0 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = 3.0 -offset_top = -62.0 -offset_right = -4.0 -offset_bottom = -4.0 -grow_horizontal = 2 -grow_vertical = 0 - -[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="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("2_hfvdi")] -unique_name_in_owner = true -layout_mode = 2 -size_flags_vertical = 3 -text = "Dialogue..." -skip_pause_at_abbreviations = PackedStringArray("Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex") - -[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 = -124.0 -offset_top = -218.0 -offset_right = 125.0 -offset_bottom = -50.0 -grow_horizontal = 2 -grow_vertical = 0 - -[node name="ResponsesMenu" type="VBoxContainer" parent="Balloon/Responses"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_vertical = 8 -theme_override_constants/separation = 2 -script = ExtResource("3_1j1j0") - -[node name="ResponseExample" type="Button" parent="Balloon/Responses/ResponsesMenu"] -layout_mode = 2 -text = "Response Example" - -[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"] diff --git a/addons/dialogue_manager/import_plugin.gd b/addons/dialogue_manager/import_plugin.gd deleted file mode 100644 index 3f0af15..0000000 --- a/addons/dialogue_manager/import_plugin.gd +++ /dev/null @@ -1,113 +0,0 @@ -@tool -extends EditorImportPlugin - - -signal compiled_resource(resource: Resource) - - -const DialogueResource = preload("./dialogue_resource.gd") -const DialogueManagerParseResult = preload("./components/parse_result.gd") - -const compiler_version = 11 - - -func _get_importer_name() -> String: - # NOTE: A change to this forces a re-import of all dialogue - return "dialogue_manager_compiler_%s" % compiler_version - - -func _get_visible_name() -> String: - return "Dialogue" - - -func _get_import_order() -> int: - return -1000 - - -func _get_priority() -> float: - return 1000.0 - - -func _get_resource_type(): - return "Resource" - - -func _get_recognized_extensions() -> PackedStringArray: - return PackedStringArray(["dialogue"]) - - -func _get_save_extension(): - return "tres" - - -func _get_preset_count() -> int: - return 0 - - -func _get_preset_name(preset_index: int) -> String: - return "Unknown" - - -func _get_import_options(path: String, preset_index: int) -> Array: - # When the options array is empty there is a misleading error on export - # that actually means nothing so let's just have an invisible option. - return [{ - name = "defaults", - default_value = true - }] - - -func _get_option_visibility(path: String, option_name: StringName, options: Dictionary) -> bool: - return false - - -func _import(source_file: String, save_path: String, options: Dictionary, platform_variants: Array[String], gen_files: Array[String]) -> Error: - var cache = Engine.get_meta("DialogueCache") - - # Get the raw file contents - if not FileAccess.file_exists(source_file): return ERR_FILE_NOT_FOUND - - var file: FileAccess = FileAccess.open(source_file, FileAccess.READ) - var raw_text: String = file.get_as_text() - - # Parse the text - var parser: DialogueManagerParser = DialogueManagerParser.new() - var err: Error = parser.parse(raw_text, source_file) - var data: DialogueManagerParseResult = parser.get_data() - var errors: Array[Dictionary] = parser.get_errors() - parser.free() - - if err != OK: - printerr("%d errors found in %s" % [errors.size(), source_file]) - cache.add_errors_to_file(source_file, errors) - return err - - # Get the current addon version - var config: ConfigFile = ConfigFile.new() - config.load("res://addons/dialogue_manager/plugin.cfg") - var version: String = config.get_value("plugin", "version") - - # Save the results to a resource - var resource: DialogueResource = DialogueResource.new() - resource.set_meta("dialogue_manager_version", version) - - resource.using_states = data.using_states - resource.titles = data.titles - resource.first_title = data.first_title - resource.character_names = data.character_names - resource.lines = data.lines - resource.raw_text = data.raw_text - - # Clear errors and possibly trigger any cascade recompiles - cache.add_file(source_file, data) - - err = ResourceSaver.save(resource, "%s.%s" % [save_path, _get_save_extension()]) - - compiled_resource.emit(resource) - - # Recompile any dependencies - var dependent_paths: PackedStringArray = cache.get_dependent_paths_for_reimport(source_file) - for path in dependent_paths: - append_import_external_resource(path) - - return err diff --git a/addons/dialogue_manager/l10n/en.mo b/addons/dialogue_manager/l10n/en.mo deleted file mode 100644 index 2ab4fdfdac7d7f52d3d107052e417714a09b6bdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9770 zcmb7|e~=|tRmU654>HjZFn|zEZYJRF#>`8yQCViQEZLdeWZ3Kvc4m`+N~h;_&rE0D z>wa|io7u@YBoHBGiKz+{1qJ^S!Lm$QT1xy;VkL@2Sx~i>f5Z~8fI_eo3$c`xTG7w< z{&=t7>_B1HJMY`~++XLOd(OG{^jBVe*+(OuC!n8%mM)8;-v>YR3jTN=x;lz}6imQt z!2<jV@KNwJ;KxCJ(KGyA1O5^CdhiS2kAYtY)$ZTGSA$nF7*j-V0AB~*2;K<38T@hZ z0nc9tUrYIMQ2jmuYMkE&uLGY4CGQKM=KBxuX7H6v`Udb$Q0-2G*MnV;kAmv=Nnigg zC^^0e-T;0Bd=+>Zi;+C91=ar+Q2kDTny>3|2fT^$$3TtqhaNA2>i18e<i7lsPQL3w z$#)c#9^d85wJ$&E%by168a)SU9T!3A{~tlg_dSnS!BqKr5LPq;UI88f)qft;Iu?EX zsxNPXY)SNMzWgyzdj2g?<NT@Te+lFleT_d<9R0iJYf`P_I#B&?12yk4P<mJZC3gZ| z1#W<v?=evN`jD@G29%u7gBtIzJ$@UM-d@4rw}Ll-(&tG~dRqngMUU~P^?d|X|4)Oe ze-6}s{hcqr2pY<-qVb!+gB~9QHUE1-+1sy!lJip_B1FIA%g=$*%a=g4{|d;E(YHZ< zcCnK8Iu@;Vw}5h?Sy1E5fd)JeO3n@Njo?$D^zjFv`oG}o|J9eTf{95+H-eIT2Ba!l z1f}OSQ1<v3sC9n=)IR+lsD1l0Q2j50lJ_5c{dax+|AJcgwfw1mAE@@TpaJg%wZ0tG zygQ)w;lrTje+FcT=<}fT@@4RfmqpP(gO^kOE{(MRFM`s;%MnuTt^*YZZU(2o{h;Q* z6V!T6fLDSKfm+WRsP;pUp`%B@JHV$v`Tg^r|4nc|<(ELow~xWJA4kD`;2BW;H$6TH z{uJe>L9Oq3Q1ZP1PJ`bB?*gaTv|GS?K=rRc?ccA0Ocgx?N-uxu%U=f%Q~n=N?GI5Y zJ)ZH{1^Gpr{7Ek#@%S_-eSQ{{++PGG-`|6h@4rFm=~|3i<(om35Bc&*Q2ibPwT=OJ z7x*Z61pE_F`us0Y^Ipl|iodT1<-czMrT4diYIiRvJ3jBr?*?Tb>%P1N%3nSRs@;b@ z|C6Bh{WGBK;CDU$Sx|cT3sC+37L@$o@c1Gq`L8AzOOES7wYwR-4ZIDMK4Y*0Zh$Ai zr$O1nzkmn98(7qx;5$I^KL8#AKMOKN^c|3<(KW{DWya$=DE<E?DE)j6{8{iKsQy>r ztiq$9^m_r+I8T7ukKX`g&wmWcUOx{?FMkDUJ%0mgJzoZ;$8UN5e}Y=~OQ70cgYl{T z>%gA@Zv=l1JPH0h_&#ty_^ijTf{#<4!WnJ{p9D4k=RmeP`g8Ck_*L*>a0cVmd>{At z8BlioEU36~5tMvi^Y|T5_V5y@bzV&{Qhx(V54VGo^C-wKTIcW0;8URX_Y0t1H>mdC z^7uUvk)kVpI*MKf>XCg&X6@qzNRQPC_?QYjk2|n3XrJ`F4SGAI`91)xK@1;lLbApC zAnEWukRAi=KpT+OJb-FQ&wC;HLj|os;gJr{Ko3CggMJA*0O|Q4^eEI<!9Of3`Vr_M z=-rTXAD(-8xyu*s4opyb{uOBGdD~zH{Q~q>=ocY9=ONj)9_^L%xC+TW2^02_uQbp+ z^n~SH`ga%>ValFEggYB2<RkY$%g`)z3-lUD&pITZn1gPG-U7WJ3XlBmGAM=Q8+w+Y z%OTmwBaj~1sh&mXgne_iRq&2`TKn<r=(K<7dVC|;gB0Um4jqSPptI0Bp<|Hz=M?k~ zsDxyH3s3^x4^2aQI*@E%&rt_9)=c^L2R**aqd>kFLpih$+JfYl=b&GPM$htaWhJXR z-CkK|QM(W)z1}3FY}T?WUdek|J*p@NTb2_Kl4dP%>ttgzmfquJ)S+H0H{-l;qioep z){nYnv65H)*oiPv>ZEzyO{#RVO~;O(mfbqas;aE&PSUHgB;AVh{-CUyEDd}HOY<f# zi+C-m<D!gVG+EJv`gAzx<=v#o;(XMn#j~Sb+P2A?UKZF{f6#2j6D(<n$(nej92TQ- zooum_IP}hoZrLC7G9<_@463ZI5q4a;k@WKPhpJ(&DyI2xBv@X!-g%L-;zU~5J+P`S z>}J}f#Ko|`oK<_*)lHQbtD)}UVSf-eC7bHzn^47iwsol{dU=6K6lvUNy~*lG;(pHZ zi&bj~!sROIu4kjo3f1GSDl!Zxom9RPfA8%c7AQIEs!zgHt3|(M3$4oKvg~EaNL}rk zNs(GLvfe#}Znr3V<1Lur_xnlE<^<mx?;dq&IZ{ijM}|(zl|AgG)n;W_blbMjs+!#M zRz*3;s-!7L=FqB|w1rm1MpEU;^4L#?#d=Y0wsdNX6MLt)P<N|*5Y`rN=FM8XJj{D( zWW!F}%j>4YYlCgBW`)GcU}8^sT1Vc+R;rR{Qg1|gQD;@-p_ABk)5>x?$q=JW(v76( zW`URHNv~YRhkP3;bT?1-9_lNsn7JgtXk5>0vJ0b`@#{g!tf5=ImaJ#-@^ZIKM?50o zpvP)P<2XO^f;3wL8P^~gjz{sldXQny-L<5^lYH|{1zkUWA(JQ~_OKwzXGs-TSr@za zf!y+mjF&Q1W4pzPZ5vg?qRIPNC#kB0SgYU>m%~QmFDug3qZT&E#c9?gd2f=rt4$r( zS>_v#t3oJgg~TxTWIzerUbfN@;@Pb_e<X{$Nult&tb<2xt{72{<mhM3TAA9g)a8t` zMj8fc)w$puDq3epi^ay4!wUNeyg?;j;XoLN|4=1ClHOhwrDoOkZfaXLtCHXvdU>~r zHLP{PaYa2GxYI6n8{%Yd^&B@yb8GuawMER;>i2B*o+0*E6*?|`D|dMJdfrxS5lbTo z(y&(4mz!C3c*nrHYn^`5bl2DithII=LT?k^Ip{X>a#)9Qm0|j5(Kq!)djZ+SQa}jJ znsRlOgLbmBJqNAt)mhV^R88VutjG7tBpq|wYr$`89FWzwx^#zigM;Ii4WWsEGw#cF zmQ@yqQ>o^N&D;sx>d*P!8>U&jf+JvsArQ1$g#H-z_u<CahE(TQQDmFQ<ATMQYp-9U zHs}{C)c&N|N;2&6y2lEv$n~z_Ju@85qai(?`&-p?hfPb?%_<qh9Br#U4%#c8x4npN z2$IB-S|L2Lf{bFS4RZBFSZ~@JF&w0*wUcb1KkKNTk#dx1D`QuVcCp#_z;c=orM!+u zV_8!P1BC_!!L(+dteyB#DP>r)T$k`XW@>&yO*iXtMl}tG`($0YzBivB@i4cL(7GOW zyIh2#vyMHpkj~tXcVURLX5Jr2=2TK}Q>v!Uo|!p^^Qd-a9@Wg6sr!<;nOX8$D=W(> zR);j7S;~@rt2}GcZ0gj)spI1b?&#b;HRmqHGfP_o#*_2hhCk-TVI%**0*;(tIx%x- z+)i_mG|U|5_L`#WS#xMPZ>G-nhE>v=IZ;;qde#&JTda>9JZ#+Sk^P0a>4>@Gz~QL} zXYO&Qx8yxrX57-vot=Z7gHzF*%|z_KQ3~STZ0=#~B_Nt3>9DWHTK%H34gHy<?sPiQ zA}NN+3v&W<TXZRgt#wCaZJN^T+g8t=eMh5tpJ23GMDt25)ExnAVqrpJ(TVOhqol&< z+&9)@Oj0nVF4|e@*vps@Vl<s-X)UkK!o1->3|AI(a7)q{ooGHJB7P=QBpkGK&8n>3 zF)`L-jN+ha){-VPR7z4Cckr3z%-FP~;}*e8#-3(jz=T0v9wI$)_SB;VTD^9n1(%m# zU}k&>ccSB?97RI;V_L24)xXu0`6^@6k#TJ+5t(FOK(1Z#uOgRSV`AK`wB5v%MQ=;n z!1V$}_6D5%!+uufU2CxJa6-YU?^|o#$g7*1<Q|j+RLoYEVE4^QZ#CPAPG(zXdYf>( zGi_R$JFZOApzv+&*v_qHyIb~#{bFa<Z2Mrj6P<DyjPc2U@fnPt-<k{a`;f1>7v|dw z({${eOKa4L>D+#k&mfFlGd9*C9Bk3hS+v_gt;I|qd8;{odVabSogbw-ctuEcCfGj7 zndG_jW`cLgT3SP+g0h%wU6Rb~;`lUXf=dE3QRb#?%9WM{P1J^@Wr7(Dqa{zcB~7$* zDar&ZBqw6pJjB#nSQCaA%H9~>Sq{ybLd)1)wz%;bm!@=xF&9vO*0<Ki3*J<1nPe5i z>_qCU=pZ{=p<y`n!eGl8UXmFGl;aw1c6zVOs`Y*150@+-@_e++Tx?mGucHO~al(~D zWK-f}<`(Z)6kKq*&)q)hxtnaqgls3AD$#MY9;AxiF8837U3zrRrZ#r`Iuz`^>Rd=> z7L~=AW5?!{#Vn1|mnHjkgtJ5*<`NcPu$hWC+UNmk)py>uxx|hPV7n=sq_;!V=h|po zQsQ-Rx|}SZQAWc`h1kB%23Ac{Vn*W)8;$9b6TR7sGTv=*2RFG-5!`un+mE$#cH41s zlAfKgV}u*KLqTWuuyh;!!#6jJS!T`*n*q`(Ou96QAT_-`j<p0IB837%qBxqTE!RL& zYmPg6$1272@r9q&jte`}(S4*!tc{JY^E8|Exz_m+5+@8og1LO4EmTOIjH@ChGgG;& ziw(2v)nnW+DYmSU8+WNR`?uZ8&H*}VAMMvfX4@6^B1~YU`jC4Wu2UN<C6$~Z|7uGb zcoOmZ&#c}dMZ^Ev132~%?j9|MEY2v4Gd7DGhm&z&n&VC*&j=cdb<#7N70w%IUKjfs zGfLk&(GTj>-s}Hg$8o-gt?io8-KTmz?|b2T<T5{d>97|mA8c&3j<+`RlyX2!iX8B? zlE1Sd>pSPuJ&*R57v6Q~&qkreqRkzxm)O{|7;-wonZ2QNAt4_bANyW1JfM|E_%+Pg zTn?A5(XDbhv%e1u$KsQ4YK|dj2#ia#SyYn)(c*eOFeT~K=-9Tl>Ml1SF6@`160A7< z7%EE-5QuEz2h)A}soizPWh3J&WF0MW!E8ojx20A_$l>khh!$4tNuj&jP+uCY^Kj+4 zq>DX<2uJpYqkB(QD0NDafc;#{dILMq3PIQUgWoq@HgpszkjWU5l!Xv|5JRWJR>pyS zI@=sOpd3}pVo;mqxfO=g)P~0BY(l<H!a_ExL3}pa+Jh+1I)<~V;rqRU(X{+%QMq)d z<}D7+J8fkn8uwD}aqJo&!p!t!6RC)ER3G+a915Ue>GmG2)!BnKBYBZHdBbJUeX+?| zih`mGQf{~Swk2&?J(hMtb#OOxE21IQ@Y(PKB*8{Wus<;u-N%_r61a$t=z?o4s<cOz zY;B}eUD$Q%+cQ|k(fTN{v5gv)`0bcc4oj-y5@F*~&runnbvC*LViPM$v{KBVZ$irJ z>;r3ZId<fePV**i_OuTvw>zW!G&gBPjifm5Qy&z`UDTz_?y|#INDlFyZbqZg&uN2w lCarTVtC5u*F#70OVIy|S{K&hD!7oD^?9RqbGge6_`aihw)SUnT diff --git a/addons/dialogue_manager/l10n/en.po b/addons/dialogue_manager/l10n/en.po deleted file mode 100644 index bf844cb..0000000 --- a/addons/dialogue_manager/l10n/en.po +++ /dev/null @@ -1,481 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Dialogue Manager\n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: \n" -"Language-Team: \n" -"Language: de\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.2.2\n" - -msgid "start_a_new_file" -msgstr "Start a new file" - -msgid "open_a_file" -msgstr "Open a file" - -msgid "open.open" -msgstr "Open..." - -msgid "open.no_recent_files" -msgstr "No recent files" - -msgid "open.clear_recent_files" -msgstr "Clear recent files" - -msgid "save_all_files" -msgstr "Save all files" - -msgid "find_in_files" -msgstr "Find in files..." - -msgid "test_dialogue" -msgstr "Test dialogue" - -msgid "search_for_text" -msgstr "Search for text" - -msgid "insert" -msgstr "Insert" - -msgid "translations" -msgstr "Translations" - -msgid "settings" -msgstr "Settings" - -msgid "sponsor" -msgstr "Sponsor" - -msgid "show_support" -msgstr "Support Dialogue Manager" - -msgid "docs" -msgstr "Docs" - -msgid "insert.wave_bbcode" -msgstr "Wave BBCode" - -msgid "insert.shake_bbcode" -msgstr "Shake BBCode" - -msgid "insert.typing_pause" -msgstr "Typing pause" - -msgid "insert.typing_speed_change" -msgstr "Typing speed change" - -msgid "insert.auto_advance" -msgstr "Auto advance" - -msgid "insert.templates" -msgstr "Templates" - -msgid "insert.title" -msgstr "Title" - -msgid "insert.dialogue" -msgstr "Dialogue" - -msgid "insert.response" -msgstr "Response" - -msgid "insert.random_lines" -msgstr "Random lines" - -msgid "insert.random_text" -msgstr "Random text" - -msgid "insert.actions" -msgstr "Actions" - -msgid "insert.jump" -msgstr "Jump to title" - -msgid "insert.end_dialogue" -msgstr "End dialogue" - -msgid "generate_line_ids" -msgstr "Generate line IDs" - -msgid "save_characters_to_csv" -msgstr "Save character names to CSV..." - -msgid "save_to_csv" -msgstr "Save lines to CSV..." - -msgid "import_from_csv" -msgstr "Import line changes from CSV..." - -msgid "confirm_close" -msgstr "Save changes to '{path}'?" - -msgid "confirm_close.save" -msgstr "Save changes" - -msgid "confirm_close.discard" -msgstr "Discard" - -msgid "buffer.save" -msgstr "Save" - -msgid "buffer.save_as" -msgstr "Save as..." - -msgid "buffer.close" -msgstr "Close" - -msgid "buffer.close_all" -msgstr "Close all" - -msgid "buffer.close_other_files" -msgstr "Close other files" - -msgid "buffer.copy_file_path" -msgstr "Copy file path" - -msgid "buffer.show_in_filesystem" -msgstr "Show in FileSystem" - -msgid "settings.invalid_test_scene" -msgstr "\"{path}\" does not extend BaseDialogueTestScene." - -msgid "settings.revert_to_default_test_scene" -msgstr "Revert to default test scene" - -msgid "settings.default_balloon_hint" -msgstr "Custom balloon to use when calling \"DialogueManager.show_balloon()\"" - -msgid "settings.revert_to_default_balloon" -msgstr "Revert to default balloon" - -msgid "settings.default_balloon_path" -msgstr "<example balloon>" - -msgid "settings.autoload" -msgstr "Autoload" - -msgid "settings.path" -msgstr "Path" - -msgid "settings.new_template" -msgstr "New dialogue files will start with template text" - -msgid "settings.missing_keys" -msgstr "Treat missing translation keys as errors" - -msgid "settings.missing_keys_hint" -msgstr "If you are using static translation keys then having this enabled will help you find any lines that you haven't added a key to yet." - -msgid "settings.characters_translations" -msgstr "Export character names in translation files" - -msgid "settings.wrap_long_lines" -msgstr "Wrap long lines" - -msgid "settings.include_failed_responses" -msgstr "Include responses with failed conditions" - -msgid "settings.ignore_missing_state_values" -msgstr "Skip over missing state value errors (not recommended)" - -msgid "settings.custom_test_scene" -msgstr "Custom test scene (must extend BaseDialogueTestScene)" - -msgid "settings.default_csv_locale" -msgstr "Default CSV Locale" - -msgid "settings.states_shortcuts" -msgstr "State Shortcuts" - -msgid "settings.states_message" -msgstr "If an autoload is enabled here you can refer to its properties and methods without having to use its name." - -msgid "settings.states_hint" -msgstr "ie. Instead of \"SomeState.some_property\" you could just use \"some_property\"" - -msgid "settings.recompile_warning" -msgstr "Changing these settings will force a recompile of all dialogue. Only change them if you know what you are doing." - -msgid "settings.create_lines_for_responses_with_characters" -msgstr "Create child dialogue line for responses with character names in them" - -msgid "settings.open_in_external_editor" -msgstr "Open dialogue files in external editor" - -msgid "settings.external_editor_warning" -msgstr "Note: Syntax highlighting and detailed error checking are not supported in external editors." - -msgid "settings.include_characters_in_translations" -msgstr "Include character names in translation exports" - -msgid "settings.include_notes_in_translations" -msgstr "Include notes (## comments) in translation exports" - -msgid "settings.check_for_updates" -msgstr "Check for updates" - -msgid "n_of_n" -msgstr "{index} of {total}" - -msgid "search.find" -msgstr "Find:" - -msgid "search.find_all" -msgstr "Find all..." - -msgid "search.placeholder" -msgstr "Text to search for" - -msgid "search.replace_placeholder" -msgstr "Text to replace it with" - -msgid "search.replace_selected" -msgstr "Replace selected" - -msgid "search.previous" -msgstr "Previous" - -msgid "search.next" -msgstr "Next" - -msgid "search.match_case" -msgstr "Match case" - -msgid "search.toggle_replace" -msgstr "Replace" - -msgid "search.replace_with" -msgstr "Replace with:" - -msgid "search.replace" -msgstr "Replace" - -msgid "search.replace_all" -msgstr "Replace all" - -msgid "files_list.filter" -msgstr "Filter files" - -msgid "titles_list.filter" -msgstr "Filter titles" - -msgid "errors.key_not_found" -msgstr "Key \"{key}\" not found." - -msgid "errors.line_and_message" -msgstr "Error at {line}, {column}: {message}" - -msgid "errors_in_script" -msgstr "You have errors in your script. Fix them and then try again." - -msgid "errors_with_build" -msgstr "You need to fix dialogue errors before you can run your game." - -msgid "errors.import_errors" -msgstr "There are errors in this imported file." - -msgid "errors.already_imported" -msgstr "File already imported." - -msgid "errors.duplicate_import" -msgstr "Duplicate import name." - -msgid "errors.unknown_using" -msgstr "Unknown autoload in using statement." - -msgid "errors.empty_title" -msgstr "Titles cannot be empty." - -msgid "errors.duplicate_title" -msgstr "There is already a title with that name." - -msgid "errors.nested_title" -msgstr "Titles cannot be indented." - -msgid "errors.invalid_title_string" -msgstr "Titles can only contain alphanumeric characters and numbers." - -msgid "errors.invalid_title_number" -msgstr "Titles cannot begin with a number." - -msgid "errors.unknown_title" -msgstr "Unknown title." - -msgid "errors.jump_to_invalid_title" -msgstr "This jump is pointing to an invalid title." - -msgid "errors.title_has_no_content" -msgstr "That title has no content. Maybe change this to a \"=> END\"." - -msgid "errors.invalid_expression" -msgstr "Expression is invalid." - -msgid "errors.unexpected_condition" -msgstr "Unexpected condition." - -msgid "errors.duplicate_id" -msgstr "This ID is already on another line." - -msgid "errors.missing_id" -msgstr "This line is missing an ID." - -msgid "errors.invalid_indentation" -msgstr "Invalid indentation." - -msgid "errors.condition_has_no_content" -msgstr "A condition line needs an indented line below it." - -msgid "errors.incomplete_expression" -msgstr "Incomplete expression." - -msgid "errors.invalid_expression_for_value" -msgstr "Invalid expression for value." - -msgid "errors.file_not_found" -msgstr "File not found." - -msgid "errors.unexpected_end_of_expression" -msgstr "Unexpected end of expression." - -msgid "errors.unexpected_function" -msgstr "Unexpected function." - -msgid "errors.unexpected_bracket" -msgstr "Unexpected bracket." - -msgid "errors.unexpected_closing_bracket" -msgstr "Unexpected closing bracket." - -msgid "errors.missing_closing_bracket" -msgstr "Missing closing bracket." - -msgid "errors.unexpected_operator" -msgstr "Unexpected operator." - -msgid "errors.unexpected_comma" -msgstr "Unexpected comma." - -msgid "errors.unexpected_colon" -msgstr "Unexpected colon." - -msgid "errors.unexpected_dot" -msgstr "Unexpected dot." - -msgid "errors.unexpected_boolean" -msgstr "Unexpected boolean." - -msgid "errors.unexpected_string" -msgstr "Unexpected string." - -msgid "errors.unexpected_number" -msgstr "Unexpected number." - -msgid "errors.unexpected_variable" -msgstr "Unexpected variable." - -msgid "errors.invalid_index" -msgstr "Invalid index." - -msgid "errors.unexpected_assignment" -msgstr "Unexpected assignment." - -msgid "errors.unknown" -msgstr "Unknown syntax." - -msgid "update.available" -msgstr "v{version} available" - -msgid "update.is_available_for_download" -msgstr "Version %s is available for download!" - -msgid "update.downloading" -msgstr "Downloading..." - -msgid "update.download_update" -msgstr "Download update" - -msgid "update.needs_reload" -msgstr "The project needs to be reloaded to install the update." - -msgid "update.reload_ok_button" -msgstr "Reload project" - -msgid "update.reload_cancel_button" -msgstr "Do it later" - -msgid "update.reload_project" -msgstr "Reload project" - -msgid "update.release_notes" -msgstr "Read release notes" - -msgid "update.success" -msgstr "Dialogue Manager is now v{version}." - -msgid "update.failed" -msgstr "There was a problem downloading the update." - -msgid "runtime.no_resource" -msgstr "No dialogue resource provided." - -msgid "runtime.no_content" -msgstr "\"{file_path}\" has no content." - -msgid "runtime.errors" -msgstr "You have {count} errors in your dialogue text." - -msgid "runtime.error_detail" -msgstr "Line {line}: {message}" - -msgid "runtime.errors_see_details" -msgstr "You have {count} errors in your dialogue text. See Output for details." - -msgid "runtime.invalid_expression" -msgstr "\"{expression}\" is not a valid expression: {error}" - -msgid "runtime.array_index_out_of_bounds" -msgstr "Index {index} out of bounds of array \"{array}\"." - -msgid "runtime.left_hand_size_cannot_be_assigned_to" -msgstr "Left hand side of expression cannot be assigned to." - -msgid "runtime.key_not_found" -msgstr "Key \"{key}\" not found in dictionary \"{dictionary}\"" - -msgid "runtime.property_not_found" -msgstr "\"{property}\" is not a property on any game states ({states})." - -msgid "runtime.property_not_found_missing_export" -msgstr "\"{property}\" is not a property on any game states ({states}). You might need to add an [Export] decorator." - -msgid "runtime.method_not_found" -msgstr "\"{method}\" is not a method on any game states ({states})" - -msgid "runtime.signal_not_found" -msgstr "\"{signal_name}\" is not a signal on any game states ({states})" - -msgid "runtime.method_not_callable" -msgstr "\"{method}\" is not a callable method on \"{object}\"" - -msgid "runtime.unknown_operator" -msgstr "Unknown operator." - -msgid "runtime.unknown_autoload" -msgstr "\"{autoload}\" doesn't appear to be a valid autoload." - -msgid "runtime.something_went_wrong" -msgstr "Something went wrong." - -msgid "runtime.expected_n_got_n_args" -msgstr "\"{method}\" was called with {received} arguments but it only has {expected}." - -msgid "runtime.unsupported_array_type" -msgstr "Array[{type}] isn't supported in mutations. Use Array as a type instead." - -msgid "runtime.dialogue_balloon_missing_start_method" -msgstr "Your dialogue balloon is missing a \"start\" or \"Start\" method." \ No newline at end of file diff --git a/addons/dialogue_manager/l10n/es.po b/addons/dialogue_manager/l10n/es.po deleted file mode 100644 index 3cbaa32..0000000 --- a/addons/dialogue_manager/l10n/es.po +++ /dev/null @@ -1,457 +0,0 @@ -# -msgid "" -msgstr "" -"Project-Id-Version: Dialogue Manager\n" -"POT-Creation-Date: 2024-02-25 20:58\n" -"PO-Revision-Date: 2024-02-25 20:58\n" -"Last-Translator: you <you@example.com>\n" -"Language-Team: Spanish <yourteam@example.com>\n" -"Language: es\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" - -msgid "start_a_new_file" -msgstr "Crear un nuevo archivo" - -msgid "open_a_file" -msgstr "Abrir un archivo" - -msgid "open.open" -msgstr "Abrir..." - -msgid "open.no_recent_files" -msgstr "No hay archivos recientes" - -msgid "open.clear_recent_files" -msgstr "Limpiar archivos recientes" - -msgid "save_all_files" -msgstr "Guardar todos los archivos" - -msgid "test_dialogue" -msgstr "Diálogo de prueba" - -msgid "search_for_text" -msgstr "Buscar texto" - -msgid "insert" -msgstr "Insertar" - -msgid "translations" -msgstr "Traducciones" - -msgid "settings" -msgstr "Ajustes" - -msgid "show_support" -msgstr "Contribuye con Dialogue Manager" - -msgid "docs" -msgstr "Docs" - -msgid "insert.wave_bbcode" -msgstr "BBCode ondulado" - -msgid "insert.shake_bbcode" -msgstr "BBCode agitado" - -msgid "insert.typing_pause" -msgstr "Pausa de escritura" - -msgid "insert.typing_speed_change" -msgstr "Cambiar la velocidad de escritura" - -msgid "insert.auto_advance" -msgstr "Avance automático" - -msgid "insert.templates" -msgstr "Plantillas" - -msgid "insert.title" -msgstr "Título" - -msgid "insert.dialogue" -msgstr "Diálogo" - -msgid "insert.response" -msgstr "Respuesta" - -msgid "insert.random_lines" -msgstr "Líneas aleatorias" - -msgid "insert.random_text" -msgstr "Texto aleatorio" - -msgid "insert.actions" -msgstr "Acciones" - -msgid "insert.jump" -msgstr "Ir al título" - -msgid "insert.end_dialogue" -msgstr "Finalizar diálogo" - -msgid "generate_line_ids" -msgstr "Generar IDs de línea" - -msgid "save_characters_to_csv" -msgstr "Guardar los nombres de los personajes en un archivo CSV..." - -msgid "save_to_csv" -msgstr "Guardar líneas en CSV..." - -msgid "import_from_csv" -msgstr "Importar cambios de línea desde CSV..." - -msgid "confirm_close" -msgstr "¿Guardar los cambios en '{path}'?" - -msgid "confirm_close.save" -msgstr "Guardar cambios" - -msgid "confirm_close.discard" -msgstr "Descartar" - -msgid "buffer.save" -msgstr "Guardar" - -msgid "buffer.save_as" -msgstr "Guardar como..." - -msgid "buffer.close" -msgstr "Cerrar" - -msgid "buffer.close_all" -msgstr "Cerrar todo" - -msgid "buffer.close_other_files" -msgstr "Cerrar otros archivos" - -msgid "buffer.copy_file_path" -msgstr "Copiar la ruta del archivo" - -msgid "buffer.show_in_filesystem" -msgstr "Mostrar en el sistema de archivos" - -msgid "settings.invalid_test_scene" -msgstr "\"{path}\" no extiende BaseDialogueTestScene." - -msgid "settings.revert_to_default_test_scene" -msgstr "Revertir a la escena de prueba por defecto" - -msgid "settings.default_balloon_hint" -msgstr "" -"Globo personalizado para usar al llamar a \"DialogueManager.show_balloon()\"" - -msgid "settings.revert_to_default_balloon" -msgstr "Volver al globo predeterminado" - -msgid "settings.default_balloon_path" -msgstr "<globo de ejemplo>" - -msgid "settings.autoload" -msgstr "Autocarga" - -msgid "settings.path" -msgstr "Ruta" - -msgid "settings.new_template" -msgstr "Los nuevos archivos de diálogo empezarán con una plantilla" - -msgid "settings.missing_keys" -msgstr "Tratar las claves de traducción faltantes como errores" - -msgid "settings.missing_keys_hint" -msgstr "Si estás utilizando claves de traducción estáticas, tener esta opción habilitada te ayudará a encontrar cualquier línea a la que aún no le hayas añadido una clave." - -msgid "settings.characters_translations" -msgstr "Exportar nombres de personajes en archivos de traducción" - -msgid "settings.wrap_long_lines" -msgstr "Romper líneas largas" - -msgid "settings.include_failed_responses" -msgstr "Incluir respuestas con condiciones fallidas" - -msgid "settings.ignore_missing_state_values" -msgstr "Omitir errores de valores de estado faltantes (no recomendado)" - -msgid "settings.custom_test_scene" -msgstr "Escena de prueba personalizada (debe extender BaseDialogueTestScene)" - -msgid "settings.default_csv_locale" -msgstr "Localización CSV por defecto" - -msgid "settings.states_shortcuts" -msgstr "Atajos de teclado" - -msgid "settings.states_message" -msgstr "Si un autoload está habilitado aquí, puedes referirte a sus propiedades y métodos sin tener que usar su nombre." - -msgid "settings.states_hint" -msgstr "ie. En lugar de \"SomeState.some_property\" podría simplemente usar \"some_property\"" - -msgid "settings.recompile_warning" -msgstr "Cambiar estos ajustes obligará a recompilar todo el diálogo. Hazlo solo si sabes lo que estás haciendo." - -msgid "settings.create_lines_for_responses_with_characters" -msgstr "Crear línea de diálogo para respuestas con nombres de personajes dentro." - -msgid "settings.open_in_external_editor" -msgstr "Abrir archivos de diálogo en el editor externo" - -msgid "settings.external_editor_warning" -msgstr "Nota: El resaltado de sintaxis y la verificación detallada de errores no están soportados en editores externos." - -msgid "settings.include_characters_in_translations" -msgstr "Incluir nombres de personajes en las exportaciones de traducción" - -msgid "settings.include_notes_in_translations" -msgstr "Incluir notas (## comentarios) en las exportaciones de traducción" - -msgid "n_of_n" -msgstr "{index} de {total}" - -msgid "search.previous" -msgstr "Anterior" - -msgid "search.next" -msgstr "Siguiente" - -msgid "search.match_case" -msgstr "Coincidir mayúsculas/minúsculas" - -msgid "search.toggle_replace" -msgstr "Reemplazar" - -msgid "search.replace_with" -msgstr "Reemplazar con:" - -msgid "search.replace" -msgstr "Reemplazar" - -msgid "search.replace_all" -msgstr "Reemplazar todo" - -msgid "files_list.filter" -msgstr "Filtrar archivos" - -msgid "titles_list.filter" -msgstr "Filtrar títulos" - -msgid "errors.key_not_found" -msgstr "La tecla \"{key}\" no se encuentra." - -msgid "errors.line_and_message" -msgstr "Error en {line}, {column}: {message}" - -msgid "errors_in_script" -msgstr "Tienes errores en tu guion. Corrígelos y luego inténtalo de nuevo." - -msgid "errors_with_build" -msgstr "Debes corregir los errores de diálogo antes de poder ejecutar tu juego." - -msgid "errors.import_errors" -msgstr "Hay errores en este archivo importado." - -msgid "errors.already_imported" -msgstr "Archivo ya importado." - -msgid "errors.duplicate_import" -msgstr "Nombre de importación duplicado." - -msgid "errors.unknown_using" -msgstr "Autoload desconocida en la declaración de uso." - -msgid "errors.empty_title" -msgstr "Los títulos no pueden estar vacíos." - -msgid "errors.duplicate_title" -msgstr "Ya hay un título con ese nombre." - -msgid "errors.nested_title" -msgstr "Los títulos no pueden tener sangría." - -msgid "errors.invalid_title_string" -msgstr "Los títulos solo pueden contener caracteres alfanuméricos y números." - -msgid "errors.invalid_title_number" -msgstr "Los títulos no pueden empezar con un número." - -msgid "errors.unknown_title" -msgstr "Título desconocido." - -msgid "errors.jump_to_invalid_title" -msgstr "Este salto está apuntando a un título inválido." - -msgid "errors.title_has_no_content" -msgstr "Ese título no tiene contenido. Quizá cambiarlo a \"=> FIN\"." - -msgid "errors.invalid_expression" -msgstr "La expresión es inválida." - -msgid "errors.unexpected_condition" -msgstr "Condición inesperada." - -msgid "errors.duplicate_id" -msgstr "Este ID ya está en otra línea." - -msgid "errors.missing_id" -msgstr "Esta línea está sin ID." - -msgid "errors.invalid_indentation" -msgstr "Sangría no válida." - -msgid "errors.condition_has_no_content" -msgstr "Una línea de condición necesita una línea sangrada debajo de ella." - -msgid "errors.incomplete_expression" -msgstr "Expresión incompleta." - -msgid "errors.invalid_expression_for_value" -msgstr "Expresión no válida para valor." - -msgid "errors.file_not_found" -msgstr "Archivo no encontrado." - -msgid "errors.unexpected_end_of_expression" -msgstr "Fin de expresión inesperado." - -msgid "errors.unexpected_function" -msgstr "Función inesperada." - -msgid "errors.unexpected_bracket" -msgstr "Corchete inesperado." - -msgid "errors.unexpected_closing_bracket" -msgstr "Bracket de cierre inesperado." - -msgid "errors.missing_closing_bracket" -msgstr "Falta cerrar corchete." - -msgid "errors.unexpected_operator" -msgstr "Operador inesperado." - -msgid "errors.unexpected_comma" -msgstr "Coma inesperada." - -msgid "errors.unexpected_colon" -msgstr "Dos puntos inesperados" - -msgid "errors.unexpected_dot" -msgstr "Punto inesperado." - -msgid "errors.unexpected_boolean" -msgstr "Booleano inesperado." - -msgid "errors.unexpected_string" -msgstr "String inesperado." - -msgid "errors.unexpected_number" -msgstr "Número inesperado." - -msgid "errors.unexpected_variable" -msgstr "Variable inesperada." - -msgid "errors.invalid_index" -msgstr "Índice no válido." - -msgid "errors.unexpected_assignment" -msgstr "Asignación inesperada." - -msgid "errors.unknown" -msgstr "Sintaxis desconocida." - -msgid "update.available" -msgstr "v{version} disponible" - -msgid "update.is_available_for_download" -msgstr "¡La versión %s ya está disponible para su descarga!" - -msgid "update.downloading" -msgstr "Descargando..." - -msgid "update.download_update" -msgstr "Descargar actualización" - -msgid "update.needs_reload" -msgstr "El proyecto debe ser recargado para instalar la actualización." - -msgid "update.reload_ok_button" -msgstr "Recargar proyecto" - -msgid "update.reload_cancel_button" -msgstr "Hazlo más tarde" - -msgid "update.reload_project" -msgstr "Recargar proyecto" - -msgid "update.release_notes" -msgstr "Leer las notas de la versión" - -msgid "update.success" -msgstr "El Gestor de Diálogo ahora es v{versión}." - -msgid "update.failed" -msgstr "Hubo un problema al descargar la actualización." - -msgid "runtime.no_resource" -msgstr "Recurso de diálogo no proporcionado." - -msgid "runtime.no_content" -msgstr "\"{file_path}\" no tiene contenido." - -msgid "runtime.errors" -msgstr "Tienes {count} errores en tu diálogo de texto." - -msgid "runtime.error_detail" -msgstr "Línea {line}: {message}" - -msgid "runtime.errors_see_details" -msgstr "Tienes {count} errores en tu texto de diálogo. Consulta la salida para más detalles." - -msgid "runtime.invalid_expression" -msgstr "\"{expression}\" no es una expresión válida: {error}" - -msgid "runtime.array_index_out_of_bounds" -msgstr "Índice {index} fuera de los límites del array \"{array}\"." - -msgid "runtime.left_hand_size_cannot_be_assigned_to" -msgstr "El lado izquierdo de la expresión no se puede asignar." - -msgid "runtime.key_not_found" -msgstr "Clave \"{key}\" no encontrada en el diccionario \"{dictionary}\"" - -msgid "runtime.property_not_found" -msgstr "\"{property}\" no es una propiedad en ningún estado del juego ({states})." - -msgid "runtime.property_not_found_missing_export" -msgstr "\"{property}\" no es una propiedad en ningún estado del juego ({states}). Es posible que necesites añadir un decorador [Export]." - -msgid "runtime.method_not_found" -msgstr "\"{method}\" no es un método en ningún estado del juego ({states})" - -msgid "runtime.signal_not_found" -msgstr "\"{signal_name}\" no es una señal en ningún estado del juego ({states})" - -msgid "runtime.method_not_callable" -msgstr "\"{method}\" no es un método llamable en \"{object}\"" - -msgid "runtime.unknown_operator" -msgstr "Operador desconocido." - -msgid "runtime.unknown_autoload" -msgstr "\"{autoload}\" parece no ser un autoload válido." - -msgid "runtime.something_went_wrong" -msgstr "Algo salió mal." - -msgid "runtime.expected_n_got_n_args" -msgstr "El método \"{method}\" se llamó con {received} argumentos, pero solo tiene {expected}." - -msgid "runtime.unsupported_array_type" -msgstr "Array[{type}] no está soportado en mutaciones. Utiliza Array como tipo en su lugar." - -msgid "runtime.dialogue_balloon_missing_start_method" -msgstr "Tu globo de diálogo no tiene un método \"start\" o \"Start\"." diff --git a/addons/dialogue_manager/l10n/translations.pot b/addons/dialogue_manager/l10n/translations.pot deleted file mode 100644 index 4aeec3b..0000000 --- a/addons/dialogue_manager/l10n/translations.pot +++ /dev/null @@ -1,471 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Dialogue Manager\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8-bit\n" - -msgid "start_a_new_file" -msgstr "" - -msgid "open_a_file" -msgstr "" - -msgid "open.open" -msgstr "" - -msgid "open.no_recent_files" -msgstr "" - -msgid "open.clear_recent_files" -msgstr "" - -msgid "save_all_files" -msgstr "" - -msgid "find_in_files" -msgstr "" - -msgid "test_dialogue" -msgstr "" - -msgid "search_for_text" -msgstr "" - -msgid "insert" -msgstr "" - -msgid "translations" -msgstr "" - -msgid "settings" -msgstr "" - -msgid "sponsor" -msgstr "" - -msgid "show_support" -msgstr "" - -msgid "docs" -msgstr "" - -msgid "insert.wave_bbcode" -msgstr "" - -msgid "insert.shake_bbcode" -msgstr "" - -msgid "insert.typing_pause" -msgstr "" - -msgid "insert.typing_speed_change" -msgstr "" - -msgid "insert.auto_advance" -msgstr "" - -msgid "insert.templates" -msgstr "" - -msgid "insert.title" -msgstr "" - -msgid "insert.dialogue" -msgstr "" - -msgid "insert.response" -msgstr "" - -msgid "insert.random_lines" -msgstr "" - -msgid "insert.random_text" -msgstr "" - -msgid "insert.actions" -msgstr "" - -msgid "insert.jump" -msgstr "" - -msgid "insert.end_dialogue" -msgstr "" - -msgid "generate_line_ids" -msgstr "" - -msgid "save_to_csv" -msgstr "" - -msgid "import_from_csv" -msgstr "" - -msgid "confirm_close" -msgstr "" - -msgid "confirm_close.save" -msgstr "" - -msgid "confirm_close.discard" -msgstr "" - -msgid "buffer.save" -msgstr "" - -msgid "buffer.save_as" -msgstr "" - -msgid "buffer.close" -msgstr "" - -msgid "buffer.close_all" -msgstr "" - -msgid "buffer.close_other_files" -msgstr "" - -msgid "buffer.copy_file_path" -msgstr "" - -msgid "buffer.show_in_filesystem" -msgstr "" - -msgid "settings.invalid_test_scene" -msgstr "" - -msgid "settings.revert_to_default_test_scene" -msgstr "" - -msgid "settings.default_balloon_hint" -msgstr "" - -msgid "settings.revert_to_default_balloon" -msgstr "" - -msgid "settings.default_balloon_path" -msgstr "" - -msgid "settings.autoload" -msgstr "" - -msgid "settings.path" -msgstr "" - -msgid "settings.new_template" -msgstr "" - -msgid "settings.missing_keys" -msgstr "" - -msgid "settings.missing_keys_hint" -msgstr "" - -msgid "settings.characters_translations" -msgstr "" - -msgid "settings.wrap_long_lines" -msgstr "" - -msgid "settings.include_failed_responses" -msgstr "" - -msgid "settings.ignore_missing_state_values" -msgstr "" - -msgid "settings.custom_test_scene" -msgstr "" - -msgid "settings.default_csv_locale" -msgstr "" - -msgid "settings.states_shortcuts" -msgstr "" - -msgid "settings.states_message" -msgstr "" - -msgid "settings.states_hint" -msgstr "" - -msgid "settings.recompile_warning" -msgstr "" - -msgid "settings.create_lines_for_responses_with_characters" -msgstr "" - -msgid "settings.open_in_external_editor" -msgstr "" - -msgid "settings.external_editor_warning" -msgstr "" - -msgid "settings.include_characters_in_translations" -msgstr "" - -msgid "settings.include_notes_in_translations" -msgstr "" - -msgid "settings.check_for_updates" -msgstr "" - -msgid "n_of_n" -msgstr "" - -msgid "search.find" -msgstr "" - -msgid "search.find_all" -msgstr "" - -msgid "search.placeholder" -msgstr "" - -msgid "search.replace_placeholder" -msgstr "" - -msgid "search.replace_selected" -msgstr "" - -msgid "search.previous" -msgstr "" - -msgid "search.next" -msgstr "" - -msgid "search.match_case" -msgstr "" - -msgid "search.toggle_replace" -msgstr "" - -msgid "search.replace_with" -msgstr "" - -msgid "search.replace" -msgstr "" - -msgid "search.replace_all" -msgstr "" - -msgid "files_list.filter" -msgstr "" - -msgid "titles_list.filter" -msgstr "" - -msgid "errors.key_not_found" -msgstr "" - -msgid "errors.line_and_message" -msgstr "" - -msgid "errors_in_script" -msgstr "" - -msgid "errors_with_build" -msgstr "" - -msgid "errors.import_errors" -msgstr "" - -msgid "errors.already_imported" -msgstr "" - -msgid "errors.duplicate_import" -msgstr "" - -msgid "errors.unknown_using" -msgstr "" - -msgid "errors.empty_title" -msgstr "" - -msgid "errors.duplicate_title" -msgstr "" - -msgid "errors.nested_title" -msgstr "" - -msgid "errors.invalid_title_string" -msgstr "" - -msgid "errors.invalid_title_number" -msgstr "" - -msgid "errors.unknown_title" -msgstr "" - -msgid "errors.jump_to_invalid_title" -msgstr "" - -msgid "errors.title_has_no_content" -msgstr "" - -msgid "errors.invalid_expression" -msgstr "" - -msgid "errors.unexpected_condition" -msgstr "" - -msgid "errors.duplicate_id" -msgstr "" - -msgid "errors.missing_id" -msgstr "" - -msgid "errors.invalid_indentation" -msgstr "" - -msgid "errors.condition_has_no_content" -msgstr "" - -msgid "errors.incomplete_expression" -msgstr "" - -msgid "errors.invalid_expression_for_value" -msgstr "" - -msgid "errors.file_not_found" -msgstr "" - -msgid "errors.unexpected_end_of_expression" -msgstr "" - -msgid "errors.unexpected_function" -msgstr "" - -msgid "errors.unexpected_bracket" -msgstr "" - -msgid "errors.unexpected_closing_bracket" -msgstr "" - -msgid "errors.missing_closing_bracket" -msgstr "" - -msgid "errors.unexpected_operator" -msgstr "" - -msgid "errors.unexpected_comma" -msgstr "" - -msgid "errors.unexpected_colon" -msgstr "" - -msgid "errors.unexpected_dot" -msgstr "" - -msgid "errors.unexpected_boolean" -msgstr "" - -msgid "errors.unexpected_string" -msgstr "" - -msgid "errors.unexpected_number" -msgstr "" - -msgid "errors.unexpected_variable" -msgstr "" - -msgid "errors.invalid_index" -msgstr "" - -msgid "errors.unexpected_assignment" -msgstr "" - -msgid "errors.unknown" -msgstr "" - -msgid "update.available" -msgstr "" - -msgid "update.is_available_for_download" -msgstr "" - -msgid "update.downloading" -msgstr "" - -msgid "update.download_update" -msgstr "" - -msgid "update.needs_reload" -msgstr "" - -msgid "update.reload_ok_button" -msgstr "" - -msgid "update.reload_cancel_button" -msgstr "" - -msgid "update.reload_project" -msgstr "" - -msgid "update.release_notes" -msgstr "" - -msgid "update.success" -msgstr "" - -msgid "update.failed" -msgstr "" - -msgid "runtime.no_resource" -msgstr "" - -msgid "runtime.no_content" -msgstr "" - -msgid "runtime.errors" -msgstr "" - -msgid "runtime.error_detail" -msgstr "" - -msgid "runtime.errors_see_details" -msgstr "" - -msgid "runtime.invalid_expression" -msgstr "" - -msgid "runtime.array_index_out_of_bounds" -msgstr "" - -msgid "runtime.left_hand_size_cannot_be_assigned_to" -msgstr "" - -msgid "runtime.key_not_found" -msgstr "" - -msgid "runtime.property_not_found" -msgstr "" - -msgid "runtime.property_not_found_missing_export" -msgstr "" - -msgid "runtime.method_not_found" -msgstr "" - -msgid "runtime.signal_not_found" -msgstr "" - -msgid "runtime.method_not_callable" -msgstr "" - -msgid "runtime.unknown_operator" -msgstr "" - -msgid "runtime.unknown_autoload" -msgstr "" - -msgid "runtime.something_went_wrong" -msgstr "" - -msgid "runtime.expected_n_got_n_args" -msgstr "" - -msgid "runtime.unsupported_array_type" -msgstr "" - -msgid "runtime.dialogue_balloon_missing_start_method" -msgstr "" \ No newline at end of file diff --git a/addons/dialogue_manager/l10n/zh.po b/addons/dialogue_manager/l10n/zh.po deleted file mode 100644 index b7f032f..0000000 --- a/addons/dialogue_manager/l10n/zh.po +++ /dev/null @@ -1,408 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Dialogue Manager\n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: \n" -"Language-Team: penghao123456、憨憨羊の宇航鸽鸽\n" -"Language: zh\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 3.4\n" - -msgid "start_a_new_file" -msgstr "创建新文件" - -msgid "open_a_file" -msgstr "打开已有文件" - -msgid "open.open" -msgstr "打开……" - -msgid "open.no_recent_files" -msgstr "无历史记录" - -msgid "open.clear_recent_files" -msgstr "清空历史记录" - -msgid "save_all_files" -msgstr "保存所有文件" - -msgid "test_dialogue" -msgstr "测试对话" - -msgid "search_for_text" -msgstr "查找……" - -msgid "insert" -msgstr "插入" - -msgid "translations" -msgstr "翻译" - -msgid "settings" -msgstr "设置" - -msgid "show_support" -msgstr "支持 Dialogue Manager" - -msgid "docs" -msgstr "文档" - -msgid "insert.wave_bbcode" -msgstr "BBCode [lb]wave[rb]" - -msgid "insert.shake_bbcode" -msgstr "BBCode [lb]wave[rb]" - -msgid "insert.typing_pause" -msgstr "输入间隔" - -msgid "insert.typing_speed_change" -msgstr "输入速度变更" - -msgid "insert.auto_advance" -msgstr "自动切行" - -msgid "insert.templates" -msgstr "模板" - -msgid "insert.title" -msgstr "标题" - -msgid "insert.dialogue" -msgstr "对话" - -msgid "insert.response" -msgstr "回复选项" - -msgid "insert.random_lines" -msgstr "随机行" - -msgid "insert.random_text" -msgstr "随机文本" - -msgid "insert.actions" -msgstr "操作" - -msgid "insert.jump" -msgstr "标题间跳转" - -msgid "insert.end_dialogue" -msgstr "结束对话" - -msgid "generate_line_ids" -msgstr "生成行 ID" - -msgid "save_to_csv" -msgstr "生成 CSV" - -msgid "import_from_csv" -msgstr "从 CSV 导入" - -msgid "confirm_close" -msgstr "是否要保存到“{path}”?" - -msgid "confirm_close.save" -msgstr "保存" - -msgid "confirm_close.discard" -msgstr "不保存" - -msgid "buffer.save" -msgstr "保存" - -msgid "buffer.save_as" -msgstr "另存为……" - -msgid "buffer.close" -msgstr "关闭" - -msgid "buffer.close_all" -msgstr "全部关闭" - -msgid "buffer.close_other_files" -msgstr "关闭其他文件" - -msgid "buffer.copy_file_path" -msgstr "复制文件路径" - -msgid "buffer.show_in_filesystem" -msgstr "在 Godot 侧边栏中显示" - -msgid "settings.revert_to_default_test_scene" -msgstr "重置测试场景设定" - -msgid "settings.autoload" -msgstr "Autoload" - -msgid "settings.path" -msgstr "路径" - -msgid "settings.new_template" -msgstr "新建文件时自动插入模板" - -msgid "settings.missing_keys" -msgstr "将翻译键缺失视为错误" - -msgid "settings.missing_keys_hint" -msgstr "如果你使用静态键,这将会帮助你寻找未添加至翻译文件的键。" - -msgid "settings.characters_translations" -msgstr "在翻译文件中导出角色名。" - -msgid "settings.wrap_long_lines" -msgstr "自动折行" - -msgid "settings.include_failed_responses" -msgstr "在判断条件失败时仍显示回复选项" - -msgid "settings.ignore_missing_state_values" -msgstr "忽略全局变量缺失错误(不建议)" - -msgid "settings.custom_test_scene" -msgstr "自定义测试场景(必须继承自BaseDialogueTestScene)" - -msgid "settings.default_csv_locale" -msgstr "默认 CSV 区域格式" - -msgid "settings.states_shortcuts" -msgstr "全局变量映射" - -msgid "settings.states_message" -msgstr "当一个 Autoload 在这里被勾选,他的所有成员会被映射为全局变量。" - -msgid "settings.states_hint" -msgstr "比如,当你开启对于“Foo”的映射时,你可以将“Foo.bar”简写成“bar”。" - -msgid "n_of_n" -msgstr "第{index}个,共{total}个" - -msgid "search.previous" -msgstr "查找上一个" - -msgid "search.next" -msgstr "查找下一个" - -msgid "search.match_case" -msgstr "大小写敏感" - -msgid "search.toggle_replace" -msgstr "替换" - -msgid "search.replace_with" -msgstr "替换为" - -msgid "search.replace" -msgstr "替换" - -msgid "search.replace_all" -msgstr "全部替换" - -msgid "files_list.filter" -msgstr "查找文件" - -msgid "titles_list.filter" -msgstr "查找标题" - -msgid "errors.key_not_found" -msgstr "键“{key}”未找到" - -msgid "errors.line_and_message" -msgstr "第{line}行第{colume}列发生错误:{message}" - -msgid "errors_in_script" -msgstr "你的脚本中存在错误。请修复错误,然后重试。" - -msgid "errors_with_build" -msgstr "请先解决 Dialogue 中的错误。" - -msgid "errors.import_errors" -msgstr "被导入的文件存在问题。" - -msgid "errors.already_imported" -msgstr "文件已被导入。" - -msgid "errors.duplicate_import" -msgstr "导入名不能重复。" - -msgid "errors.empty_title" -msgstr "标题名不能为空。" - -msgid "errors.duplicate_title" -msgstr "标题名不能重复。" - -msgid "errors.nested_title" -msgstr "标题不能嵌套。" - -msgid "errors.invalid_title_string" -msgstr "标题名无效。" - -msgid "errors.invalid_title_number" -msgstr "标题不能以数字开始。" - -msgid "errors.unknown_title" -msgstr "标题未定义。" - -msgid "errors.jump_to_invalid_title" -msgstr "标题名无效。" - -msgid "errors.title_has_no_content" -msgstr "目标标题为空。请替换为“=> END”。" - -msgid "errors.invalid_expression" -msgstr "表达式无效。" - -msgid "errors.unexpected_condition" -msgstr "未知条件。" - -msgid "errors.duplicate_id" -msgstr "ID 重复。" - -msgid "errors.missing_id" -msgstr "ID 不存在。" - -msgid "errors.invalid_indentation" -msgstr "缩进无效。" - -msgid "errors.condition_has_no_content" -msgstr "条件下方不能为空。" - -msgid "errors.incomplete_expression" -msgstr "不完整的表达式。" - -msgid "errors.invalid_expression_for_value" -msgstr "无效的赋值表达式。" - -msgid "errors.file_not_found" -msgstr "文件不存在。" - -msgid "errors.unexpected_end_of_expression" -msgstr "表达式 end 不应存在。" - -msgid "errors.unexpected_function" -msgstr "函数不应存在。" - -msgid "errors.unexpected_bracket" -msgstr "方括号不应存在。" - -msgid "errors.unexpected_closing_bracket" -msgstr "方括号不应存在。" - -msgid "errors.missing_closing_bracket" -msgstr "闭方括号不存在。" - -msgid "errors.unexpected_operator" -msgstr "操作符不应存在。" - -msgid "errors.unexpected_comma" -msgstr "逗号不应存在。" - -msgid "errors.unexpected_colon" -msgstr "冒号不应存在。" - -msgid "errors.unexpected_dot" -msgstr "句号不应存在。" - -msgid "errors.unexpected_boolean" -msgstr "布尔值不应存在。" - -msgid "errors.unexpected_string" -msgstr "字符串不应存在。" - -msgid "errors.unexpected_number" -msgstr "数字不应存在。" - -msgid "errors.unexpected_variable" -msgstr "标识符不应存在。" - -msgid "errors.invalid_index" -msgstr "索引无效。" - -msgid "errors.unexpected_assignment" -msgstr "不应在条件判断中使用 = ,应使用 == 。" - -msgid "errors.unknown" -msgstr "语法错误。" - -msgid "update.available" -msgstr "v{version} 更新可用。" - -msgid "update.is_available_for_download" -msgstr "v%s 已经可以下载。" - -msgid "update.downloading" -msgstr "正在下载更新……" - -msgid "update.download_update" -msgstr "下载" - -msgid "update.needs_reload" -msgstr "需要重新加载项目以应用更新。" - -msgid "update.reload_ok_button" -msgstr "重新加载" - -msgid "update.reload_cancel_button" -msgstr "暂不重新加载" - -msgid "update.reload_project" -msgstr "重新加载" - -msgid "update.release_notes" -msgstr "查看发行注记" - -msgid "update.success" -msgstr "v{version} 已成功安装并应用。" - -msgid "update.failed" -msgstr "更新失败。" - -msgid "runtime.no_resource" -msgstr "找不到资源。" - -msgid "runtime.no_content" -msgstr "资源“{file_path}”为空。" - -msgid "runtime.errors" -msgstr "文件中存在{errrors}个错误。" - -msgid "runtime.error_detail" -msgstr "第{index}行:{message}" - -msgid "runtime.errors_see_details" -msgstr "文件中存在{errrors}个错误。请查看调试输出。" - -msgid "runtime.invalid_expression" -msgstr "表达式“{expression}”无效:{error}" - -msgid "runtime.array_index_out_of_bounds" -msgstr "数组索引“{index}”越界。(数组名:“{array}”)" - -msgid "runtime.left_hand_size_cannot_be_assigned_to" -msgstr "表达式左侧的变量无法被赋值。" - -msgid "runtime.key_not_found" -msgstr "键“{key}”在字典“{dictionary}”中不存在。" - -msgid "runtime.property_not_found" -msgstr "“{property}”不存在。(全局变量:{states})" - -msgid "runtime.property_not_found_missing_export" -msgstr "“{property}”不存在。(全局变量:{states})你可能需要添加一个修饰词 [Export]。" - -msgid "runtime.method_not_found" -msgstr "“{method}”不存在。(全局变量:{states})" - -msgid "runtime.signal_not_found" -msgstr "“{sighal_name}”不存在。(全局变量:{states})" - -msgid "runtime.method_not_callable" -msgstr "{method}不是对象“{object}”上的函数。" - -msgid "runtime.unknown_operator" -msgstr "未知操作符。" - -msgid "runtime.something_went_wrong" -msgstr "有什么出错了。" diff --git a/addons/dialogue_manager/l10n/zh_TW.po b/addons/dialogue_manager/l10n/zh_TW.po deleted file mode 100644 index 3bcf153..0000000 --- a/addons/dialogue_manager/l10n/zh_TW.po +++ /dev/null @@ -1,408 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Dialogue Manager\n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: \n" -"Language-Team: 憨憨羊の宇航鴿鴿\n" -"Language: zh_TW\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 3.4\n" - -msgid "start_a_new_file" -msgstr "創建新檔案" - -msgid "open_a_file" -msgstr "開啟已有檔案" - -msgid "open.open" -msgstr "開啟……" - -msgid "open.no_recent_files" -msgstr "無歷史記錄" - -msgid "open.clear_recent_files" -msgstr "清空歷史記錄" - -msgid "save_all_files" -msgstr "儲存所有檔案" - -msgid "test_dialogue" -msgstr "測試對話" - -msgid "search_for_text" -msgstr "搜尋……" - -msgid "insert" -msgstr "插入" - -msgid "translations" -msgstr "翻譯" - -msgid "settings" -msgstr "設定" - -msgid "show_support" -msgstr "支援 Dialogue Manager" - -msgid "docs" -msgstr "文檔" - -msgid "insert.wave_bbcode" -msgstr "BBCode [lb]wave[rb]" - -msgid "insert.shake_bbcode" -msgstr "BBCode [lb]wave[rb]" - -msgid "insert.typing_pause" -msgstr "輸入間隔" - -msgid "insert.typing_speed_change" -msgstr "輸入速度變更" - -msgid "insert.auto_advance" -msgstr "自動切行" - -msgid "insert.templates" -msgstr "模板" - -msgid "insert.title" -msgstr "標題" - -msgid "insert.dialogue" -msgstr "對話" - -msgid "insert.response" -msgstr "回覆選項" - -msgid "insert.random_lines" -msgstr "隨機行" - -msgid "insert.random_text" -msgstr "隨機文本" - -msgid "insert.actions" -msgstr "操作" - -msgid "insert.jump" -msgstr "標題間跳轉" - -msgid "insert.end_dialogue" -msgstr "結束對話" - -msgid "generate_line_ids" -msgstr "生成行 ID" - -msgid "save_to_csv" -msgstr "生成 CSV" - -msgid "import_from_csv" -msgstr "從 CSV 匯入" - -msgid "confirm_close" -msgstr "是否要儲存到“{path}”?" - -msgid "confirm_close.save" -msgstr "儲存" - -msgid "confirm_close.discard" -msgstr "不儲存" - -msgid "buffer.save" -msgstr "儲存" - -msgid "buffer.save_as" -msgstr "儲存爲……" - -msgid "buffer.close" -msgstr "關閉" - -msgid "buffer.close_all" -msgstr "全部關閉" - -msgid "buffer.close_other_files" -msgstr "關閉其他檔案" - -msgid "buffer.copy_file_path" -msgstr "複製檔案位置" - -msgid "buffer.show_in_filesystem" -msgstr "在 Godot 側邊欄中顯示" - -msgid "settings.revert_to_default_test_scene" -msgstr "重置測試場景設定" - -msgid "settings.autoload" -msgstr "Autoload" - -msgid "settings.path" -msgstr "路徑" - -msgid "settings.new_template" -msgstr "新建檔案時自動插入模板" - -msgid "settings.missing_keys" -msgstr "將翻譯鍵缺失視爲錯誤" - -msgid "settings.missing_keys_hint" -msgstr "如果你使用靜態鍵,這將會幫助你尋找未添加至翻譯檔案的鍵。" - -msgid "settings.wrap_long_lines" -msgstr "自動折行" - -msgid "settings.characters_translations" -msgstr "在翻譯檔案中匯出角色名。" - -msgid "settings.include_failed_responses" -msgstr "在判斷條件失敗時仍顯示回復選項" - -msgid "settings.ignore_missing_state_values" -msgstr "忽略全局變量缺失錯誤(不建議)" - -msgid "settings.custom_test_scene" -msgstr "自訂測試場景(必須繼承自BaseDialogueTestScene)" - -msgid "settings.default_csv_locale" -msgstr "預設 CSV 區域格式" - -msgid "settings.states_shortcuts" -msgstr "全局變量映射" - -msgid "settings.states_message" -msgstr "當一個 Autoload 在這裏被勾選,他的所有成員會被映射爲全局變量。" - -msgid "settings.states_hint" -msgstr "比如,當你開啓對於“Foo”的映射時,你可以將“Foo.bar”簡寫成“bar”。" - -msgid "n_of_n" -msgstr "第{index}個,共{total}個" - -msgid "search.previous" -msgstr "搜尋上一個" - -msgid "search.next" -msgstr "搜尋下一個" - -msgid "search.match_case" -msgstr "大小寫敏感" - -msgid "search.toggle_replace" -msgstr "替換" - -msgid "search.replace_with" -msgstr "替換爲" - -msgid "search.replace" -msgstr "替換" - -msgid "search.replace_all" -msgstr "全部替換" - -msgid "files_list.filter" -msgstr "搜尋檔案" - -msgid "titles_list.filter" -msgstr "搜尋標題" - -msgid "errors.key_not_found" -msgstr "鍵“{key}”未找到" - -msgid "errors.line_and_message" -msgstr "第{line}行第{colume}列發生錯誤:{message}" - -msgid "errors_in_script" -msgstr "你的腳本中存在錯誤。請修復錯誤,然後重試。" - -msgid "errors_with_build" -msgstr "請先解決 Dialogue 中的錯誤。" - -msgid "errors.import_errors" -msgstr "被匯入的檔案存在問題。" - -msgid "errors.already_imported" -msgstr "檔案已被匯入。" - -msgid "errors.duplicate_import" -msgstr "匯入名不能重複。" - -msgid "errors.empty_title" -msgstr "標題名不能爲空。" - -msgid "errors.duplicate_title" -msgstr "標題名不能重複。" - -msgid "errors.nested_title" -msgstr "標題不能嵌套。" - -msgid "errors.invalid_title_string" -msgstr "標題名無效。" - -msgid "errors.invalid_title_number" -msgstr "標題不能以數字開始。" - -msgid "errors.unknown_title" -msgstr "標題未定義。" - -msgid "errors.jump_to_invalid_title" -msgstr "標題名無效。" - -msgid "errors.title_has_no_content" -msgstr "目標標題爲空。請替換爲“=> END”。" - -msgid "errors.invalid_expression" -msgstr "表達式無效。" - -msgid "errors.unexpected_condition" -msgstr "未知條件。" - -msgid "errors.duplicate_id" -msgstr "ID 重複。" - -msgid "errors.missing_id" -msgstr "ID 不存在。" - -msgid "errors.invalid_indentation" -msgstr "縮進無效。" - -msgid "errors.condition_has_no_content" -msgstr "條件下方不能爲空。" - -msgid "errors.incomplete_expression" -msgstr "不完整的表達式。" - -msgid "errors.invalid_expression_for_value" -msgstr "無效的賦值表達式。" - -msgid "errors.file_not_found" -msgstr "檔案不存在。" - -msgid "errors.unexpected_end_of_expression" -msgstr "表達式 end 不應存在。" - -msgid "errors.unexpected_function" -msgstr "函數不應存在。" - -msgid "errors.unexpected_bracket" -msgstr "方括號不應存在。" - -msgid "errors.unexpected_closing_bracket" -msgstr "方括號不應存在。" - -msgid "errors.missing_closing_bracket" -msgstr "閉方括號不存在。" - -msgid "errors.unexpected_operator" -msgstr "操作符不應存在。" - -msgid "errors.unexpected_comma" -msgstr "逗號不應存在。" - -msgid "errors.unexpected_colon" -msgstr "冒號不應存在。" - -msgid "errors.unexpected_dot" -msgstr "句號不應存在。" - -msgid "errors.unexpected_boolean" -msgstr "布爾值不應存在。" - -msgid "errors.unexpected_string" -msgstr "字符串不應存在。" - -msgid "errors.unexpected_number" -msgstr "數字不應存在。" - -msgid "errors.unexpected_variable" -msgstr "標識符不應存在。" - -msgid "errors.invalid_index" -msgstr "索引無效。" - -msgid "errors.unexpected_assignment" -msgstr "不應在條件判斷中使用 = ,應使用 == 。" - -msgid "errors.unknown" -msgstr "語法錯誤。" - -msgid "update.available" -msgstr "v{version} 更新可用。" - -msgid "update.is_available_for_download" -msgstr "v%s 已經可以下載。" - -msgid "update.downloading" -msgstr "正在下載更新……" - -msgid "update.download_update" -msgstr "下載" - -msgid "update.needs_reload" -msgstr "需要重新加載項目以套用更新。" - -msgid "update.reload_ok_button" -msgstr "重新加載" - -msgid "update.reload_cancel_button" -msgstr "暫不重新加載" - -msgid "update.reload_project" -msgstr "重新加載" - -msgid "update.release_notes" -msgstr "查看發行註記" - -msgid "update.success" -msgstr "v{version} 已成功安裝並套用。" - -msgid "update.failed" -msgstr "更新失敗。" - -msgid "runtime.no_resource" -msgstr "找不到資源。" - -msgid "runtime.no_content" -msgstr "資源“{file_path}”爲空。" - -msgid "runtime.errors" -msgstr "檔案中存在{errrors}個錯誤。" - -msgid "runtime.error_detail" -msgstr "第{index}行:{message}" - -msgid "runtime.errors_see_details" -msgstr "檔案中存在{errrors}個錯誤。請查看調試輸出。" - -msgid "runtime.invalid_expression" -msgstr "表達式“{expression}”無效:{error}" - -msgid "runtime.array_index_out_of_bounds" -msgstr "數組索引“{index}”越界。(數組名:“{array}”)" - -msgid "runtime.left_hand_size_cannot_be_assigned_to" -msgstr "表達式左側的變量無法被賦值。" - -msgid "runtime.key_not_found" -msgstr "鍵“{key}”在字典“{dictionary}”中不存在。" - -msgid "runtime.property_not_found" -msgstr "“{property}”不存在。(全局變量:{states})" - -msgid "runtime.method_not_found" -msgstr "“{method}”不存在。(全局變量:{states})" - -msgid "runtime.signal_not_found" -msgstr "“{sighal_name}”不存在。(全局變量:{states})" - -msgid "runtime.property_not_found_missing_export" -msgstr "“{property}”不存在。(全局變量:{states})你可能需要添加一個修飾詞 [Export]。" - -msgid "runtime.method_not_callable" -msgstr "{method}不是對象“{object}”上的函數。" - -msgid "runtime.unknown_operator" -msgstr "未知操作符。" - -msgid "runtime.something_went_wrong" -msgstr "有什麼出錯了。" diff --git a/addons/dialogue_manager/plugin.cfg b/addons/dialogue_manager/plugin.cfg deleted file mode 100644 index 572ad9f..0000000 --- a/addons/dialogue_manager/plugin.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[plugin] - -name="Dialogue Manager" -description="A simple but powerful branching dialogue system" -author="Nathan Hoad" -version="2.38.0" -script="plugin.gd" diff --git a/addons/dialogue_manager/plugin.gd b/addons/dialogue_manager/plugin.gd deleted file mode 100644 index 70836f3..0000000 --- a/addons/dialogue_manager/plugin.gd +++ /dev/null @@ -1,276 +0,0 @@ -@tool -extends EditorPlugin - - -const DialogueConstants = preload("./constants.gd") -const DialogueImportPlugin = preload("./import_plugin.gd") -const DialogueTranslationParserPlugin = preload("./editor_translation_parser_plugin.gd") -const DialogueSettings = preload("./settings.gd") -const DialogueCache = preload("./components/dialogue_cache.gd") -const MainView = preload("./views/main_view.tscn") - - -var import_plugin: DialogueImportPlugin -var translation_parser_plugin: DialogueTranslationParserPlugin -var main_view -var dialogue_cache: DialogueCache - - -func _enter_tree() -> void: - add_autoload_singleton("DialogueManager", get_plugin_path() + "/dialogue_manager.gd") - - if Engine.is_editor_hint(): - Engine.set_meta("DialogueManagerPlugin", self) - - DialogueSettings.prepare() - - import_plugin = DialogueImportPlugin.new() - add_import_plugin(import_plugin) - - translation_parser_plugin = DialogueTranslationParserPlugin.new() - add_translation_parser_plugin(translation_parser_plugin) - - main_view = MainView.instantiate() - main_view.editor_plugin = self - get_editor_interface().get_editor_main_screen().add_child(main_view) - _make_visible(false) - - dialogue_cache = DialogueCache.new() - main_view.add_child(dialogue_cache) - Engine.set_meta("DialogueCache", dialogue_cache) - - _update_localization() - - get_editor_interface().get_file_system_dock().files_moved.connect(_on_files_moved) - get_editor_interface().get_file_system_dock().file_removed.connect(_on_file_removed) - - add_tool_menu_item("Create copy of dialogue example balloon...", _copy_dialogue_balloon) - - # Prevent the project from showing as unsaved even though it was only just opened - if Engine.get_physics_frames() == 0: - var timer: Timer = Timer.new() - var suppress_unsaved_marker: Callable - suppress_unsaved_marker = func(): - if Engine.get_frames_per_second() >= 10: - timer.stop() - get_editor_interface().save_all_scenes() - timer.queue_free() - timer.timeout.connect(suppress_unsaved_marker) - add_child(timer) - timer.start(0.1) - - -func _exit_tree() -> void: - remove_autoload_singleton("DialogueManager") - - remove_import_plugin(import_plugin) - import_plugin = null - - remove_translation_parser_plugin(translation_parser_plugin) - translation_parser_plugin = null - - if is_instance_valid(main_view): - main_view.queue_free() - - Engine.remove_meta("DialogueManagerPlugin") - Engine.remove_meta("DialogueCache") - - get_editor_interface().get_file_system_dock().files_moved.disconnect(_on_files_moved) - get_editor_interface().get_file_system_dock().file_removed.disconnect(_on_file_removed) - - remove_tool_menu_item("Create copy of dialogue example balloon...") - - -func _has_main_screen() -> bool: - return true - - -func _make_visible(next_visible: bool) -> void: - if is_instance_valid(main_view): - main_view.visible = next_visible - - -func _get_plugin_name() -> String: - return "Dialogue" - - -func _get_plugin_icon() -> Texture2D: - return load(get_plugin_path() + "/assets/icon.svg") - - -func _handles(object) -> bool: - var editor_settings: EditorSettings = get_editor_interface().get_editor_settings() - var external_editor: String = editor_settings.get_setting("text_editor/external/exec_path") - var use_external_editor: bool = editor_settings.get_setting("text_editor/external/use_external_editor") and external_editor != "" - if object is DialogueResource and use_external_editor and DialogueSettings.get_user_value("open_in_external_editor", false): - var project_path: String = ProjectSettings.globalize_path("res://") - var file_path: String = ProjectSettings.globalize_path(object.resource_path) - OS.create_process(external_editor, [project_path, file_path]) - return false - - return object is DialogueResource - - -func _edit(object) -> void: - if is_instance_valid(main_view) and is_instance_valid(object): - main_view.open_resource(object) - - -func _apply_changes() -> void: - if is_instance_valid(main_view): - main_view.apply_changes() - _update_localization() - - -func _build() -> bool: - # If this is the dotnet Godot then we need to check if the solution file exists - if ProjectSettings.has_setting("dotnet/project/solution_directory"): - var directory: String = ProjectSettings.get("dotnet/project/solution_directory") - var file_name: String = ProjectSettings.get("dotnet/project/assembly_name") - var has_dotnet_solution: bool = FileAccess.file_exists("res://%s/%s.sln" % [directory, file_name]) - DialogueSettings.set_user_value("has_dotnet_solution", has_dotnet_solution) - - # Ignore errors in other files if we are just running the test scene - if DialogueSettings.get_user_value("is_running_test_scene", true): return true - - if dialogue_cache != null: - var files_with_errors = dialogue_cache.get_files_with_errors() - if files_with_errors.size() > 0: - for dialogue_file in files_with_errors: - push_error("You have %d error(s) in %s" % [dialogue_file.errors.size(), dialogue_file.path]) - get_editor_interface().edit_resource(load(files_with_errors[0].path)) - main_view.show_build_error_dialog() - return false - - return true - - -## Get the current version -func get_version() -> String: - var config: ConfigFile = ConfigFile.new() - config.load(get_plugin_path() + "/plugin.cfg") - return config.get_value("plugin", "version") - - -## Get the current path of the plugin -func get_plugin_path() -> String: - return get_script().resource_path.get_base_dir() - - -## Update references to a moved file -func update_import_paths(from_path: String, to_path: String) -> void: - dialogue_cache.move_file_path(from_path, to_path) - - # Reopen the file if it's already open - if main_view.current_file_path == from_path: - if to_path == "": - main_view.close_file(from_path) - else: - main_view.current_file_path = "" - main_view.open_file(to_path) - - # Update any other files that import the moved file - var dependents = dialogue_cache.get_files_with_dependency(from_path) - for dependent in dependents: - dependent.dependencies.remove_at(dependent.dependencies.find(from_path)) - dependent.dependencies.append(to_path) - - # Update the live buffer - if main_view.current_file_path == dependent.path: - main_view.code_edit.text = main_view.code_edit.text.replace(from_path, to_path) - main_view.pristine_text = main_view.code_edit.text - - # Open the file and update the path - var file: FileAccess = FileAccess.open(dependent.path, FileAccess.READ) - var text = file.get_as_text().replace(from_path, to_path) - file.close() - - file = FileAccess.open(dependent.path, FileAccess.WRITE) - file.store_string(text) - file.close() - - -func _update_localization() -> void: - var dialogue_files = dialogue_cache.get_files() - - # Add any new files to POT generation - var files_for_pot: PackedStringArray = ProjectSettings.get_setting("internationalization/locale/translations_pot_files", []) - var files_for_pot_changed: bool = false - for path in dialogue_files: - if not files_for_pot.has(path): - files_for_pot.append(path) - files_for_pot_changed = true - - # Remove any POT references that don't exist any more - for i in range(files_for_pot.size() - 1, -1, -1): - var file_for_pot: String = files_for_pot[i] - if file_for_pot.get_extension() == "dialogue" and not dialogue_files.has(file_for_pot): - files_for_pot.remove_at(i) - files_for_pot_changed = true - - # Update project settings if POT changed - if files_for_pot_changed: - ProjectSettings.set_setting("internationalization/locale/translations_pot_files", files_for_pot) - ProjectSettings.save() - - -### Callbacks - - -func _copy_dialogue_balloon() -> void: - var scale: float = get_editor_interface().get_editor_scale() - var directory_dialog: FileDialog = FileDialog.new() - var label: Label = Label.new() - label.text = "Dialogue balloon files will be copied into chosen directory." - directory_dialog.get_vbox().add_child(label) - directory_dialog.file_mode = FileDialog.FILE_MODE_OPEN_DIR - directory_dialog.min_size = Vector2(600, 500) * scale - directory_dialog.dir_selected.connect(func(path): - var plugin_path: String = get_plugin_path() - - var is_dotnet: bool = DialogueSettings.has_dotnet_solution() - var balloon_path: String = path + ("/Balloon.tscn" if is_dotnet else "/balloon.tscn") - var balloon_script_path: String = path + ("/DialogueBalloon.cs" if is_dotnet else "/balloon.gd") - - # Copy the balloon scene file and change the script reference - var is_small_window: bool = ProjectSettings.get_setting("display/window/size/viewport_width") < 400 - var example_balloon_file_name: String = "small_example_balloon.tscn" if is_small_window else "example_balloon.tscn" - var example_balloon_script_file_name: String = "ExampleBalloon.cs" if is_dotnet else "example_balloon.gd" - var file: FileAccess = FileAccess.open(plugin_path + "/example_balloon/" + example_balloon_file_name, FileAccess.READ) - var file_contents: String = file.get_as_text().replace(plugin_path + "/example_balloon/example_balloon.gd", balloon_script_path) - file = FileAccess.open(balloon_path, FileAccess.WRITE) - file.store_string(file_contents) - file.close() - - # Copy the script file - file = FileAccess.open(plugin_path + "/example_balloon/" + example_balloon_script_file_name, FileAccess.READ) - file_contents = file.get_as_text() - if is_dotnet: - file_contents = file_contents.replace("class ExampleBalloon", "class DialogueBalloon") - file = FileAccess.open(balloon_script_path, FileAccess.WRITE) - file.store_string(file_contents) - file.close() - - get_editor_interface().get_resource_filesystem().scan() - get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", balloon_path) - - DialogueSettings.set_setting("balloon_path", balloon_path) - - directory_dialog.queue_free() - ) - get_editor_interface().get_base_control().add_child(directory_dialog) - directory_dialog.popup_centered() - - -### Signals - - -func _on_files_moved(old_file: String, new_file: String) -> void: - update_import_paths(old_file, new_file) - DialogueSettings.move_recent_file(old_file, new_file) - - -func _on_file_removed(file: String) -> void: - update_import_paths(file, "") - if is_instance_valid(main_view): - main_view.close_file(file) diff --git a/addons/dialogue_manager/settings.gd b/addons/dialogue_manager/settings.gd deleted file mode 100644 index b968a84..0000000 --- a/addons/dialogue_manager/settings.gd +++ /dev/null @@ -1,184 +0,0 @@ -@tool -extends Node - - -const DialogueConstants = preload("./constants.gd") - - -### Editor config - -const DEFAULT_SETTINGS = { - states = [], - missing_translations_are_errors = false, - export_characters_in_translation = true, - wrap_lines = false, - new_with_template = true, - include_all_responses = false, - ignore_missing_state_values = false, - custom_test_scene_path = preload("./test_scene.tscn").resource_path, - default_csv_locale = "en", - balloon_path = "", - create_lines_for_responses_with_characters = true, - include_character_in_translation_exports = false, - include_notes_in_translation_exports = false -} - - -static func prepare() -> void: - # Migrate previous keys - for key in [ - "states", - "missing_translations_are_errors", - "export_characters_in_translation", - "wrap_lines", - "new_with_template", - "include_all_responses", - "custom_test_scene_path" - ]: - if ProjectSettings.has_setting("dialogue_manager/%s" % key): - var value = ProjectSettings.get_setting("dialogue_manager/%s" % key) - ProjectSettings.set_setting("dialogue_manager/%s" % key, null) - set_setting(key, value) - - # Set up initial settings - for setting in DEFAULT_SETTINGS: - var setting_name: String = "dialogue_manager/general/%s" % setting - if not ProjectSettings.has_setting(setting_name): - set_setting(setting, DEFAULT_SETTINGS[setting]) - ProjectSettings.set_initial_value(setting_name, DEFAULT_SETTINGS[setting]) - if setting.ends_with("_path"): - ProjectSettings.add_property_info({ - "name": setting_name, - "type": TYPE_STRING, - "hint": PROPERTY_HINT_FILE, - }) - - ProjectSettings.save() - - -static func set_setting(key: String, value) -> void: - ProjectSettings.set_setting("dialogue_manager/general/%s" % key, value) - ProjectSettings.set_initial_value("dialogue_manager/general/%s" % key, DEFAULT_SETTINGS[key]) - ProjectSettings.save() - - -static func get_setting(key: String, default): - if ProjectSettings.has_setting("dialogue_manager/general/%s" % key): - return ProjectSettings.get_setting("dialogue_manager/general/%s" % key) - else: - return default - - -static func get_settings(only_keys: PackedStringArray = []) -> Dictionary: - var settings: Dictionary = {} - for key in DEFAULT_SETTINGS.keys(): - if only_keys.is_empty() or key in only_keys: - settings[key] = get_setting(key, DEFAULT_SETTINGS[key]) - return settings - - -### User config - - -static func get_user_config() -> Dictionary: - var user_config: Dictionary = { - check_for_updates = true, - just_refreshed = null, - recent_files = [], - reopen_files = [], - most_recent_reopen_file = "", - carets = {}, - run_title = "", - run_resource_path = "", - is_running_test_scene = false, - has_dotnet_solution = false, - open_in_external_editor = false - } - - if FileAccess.file_exists(DialogueConstants.USER_CONFIG_PATH): - var file: FileAccess = FileAccess.open(DialogueConstants.USER_CONFIG_PATH, FileAccess.READ) - user_config.merge(JSON.parse_string(file.get_as_text()), true) - - return user_config - - -static func save_user_config(user_config: Dictionary) -> void: - var file: FileAccess = FileAccess.open(DialogueConstants.USER_CONFIG_PATH, FileAccess.WRITE) - file.store_string(JSON.stringify(user_config)) - - -static func set_user_value(key: String, value) -> void: - var user_config: Dictionary = get_user_config() - user_config[key] = value - save_user_config(user_config) - - -static func get_user_value(key: String, default = null): - return get_user_config().get(key, default) - - -static func add_recent_file(path: String) -> void: - var recent_files: Array = get_user_value("recent_files", []) - if path in recent_files: - recent_files.erase(path) - recent_files.insert(0, path) - set_user_value("recent_files", recent_files) - - -static func move_recent_file(from_path: String, to_path: String) -> void: - var recent_files: Array = get_user_value("recent_files", []) - for i in range(0, recent_files.size()): - if recent_files[i] == from_path: - recent_files[i] = to_path - set_user_value("recent_files", recent_files) - - -static func remove_recent_file(path: String) -> void: - var recent_files: Array = get_user_value("recent_files", []) - if path in recent_files: - recent_files.erase(path) - set_user_value("recent_files", recent_files) - - -static func get_recent_files() -> Array: - return get_user_value("recent_files", []) - - -static func clear_recent_files() -> void: - set_user_value("recent_files", []) - set_user_value("carets", {}) - - -static func set_caret(path: String, cursor: Vector2) -> void: - var carets: Dictionary = get_user_value("carets", {}) - carets[path] = { - x = cursor.x, - y = cursor.y - } - set_user_value("carets", carets) - - -static func get_caret(path: String) -> Vector2: - var carets = get_user_value("carets", {}) - if carets.has(path): - var caret = carets.get(path) - return Vector2(caret.x, caret.y) - else: - return Vector2.ZERO - - -static func has_dotnet_solution() -> bool: - if get_user_value("has_dotnet_solution", false): return true - - if ProjectSettings.has_setting("dotnet/project/solution_directory"): - var directory: String = ProjectSettings.get("dotnet/project/solution_directory") - var file_name: String = ProjectSettings.get("dotnet/project/assembly_name") - var has_dotnet_solution: bool = FileAccess.file_exists("res://%s/%s.sln" % [directory, file_name]) - set_user_value("has_dotnet_solution", has_dotnet_solution) - return has_dotnet_solution - else: - var plugin_path: String = new().get_script().resource_path.get_base_dir() - if not ResourceLoader.exists(plugin_path + "/DialogueManager.cs"): return false - if load(plugin_path + "/DialogueManager.cs") == null: return false - - return true diff --git a/addons/dialogue_manager/test_scene.gd b/addons/dialogue_manager/test_scene.gd deleted file mode 100644 index 5fc073e..0000000 --- a/addons/dialogue_manager/test_scene.gd +++ /dev/null @@ -1,31 +0,0 @@ -class_name BaseDialogueTestScene extends Node2D - - -const DialogueSettings = preload("./settings.gd") - - -@onready var title: String = DialogueSettings.get_user_value("run_title") -@onready var resource: DialogueResource = load(DialogueSettings.get_user_value("run_resource_path")) - - -func _ready(): - var screen_index: int = DisplayServer.get_primary_screen() - DisplayServer.window_set_position(Vector2(DisplayServer.screen_get_position(screen_index)) + (DisplayServer.screen_get_size(screen_index) - DisplayServer.window_get_size()) * 0.5) - DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) - - # Normally you can just call DialogueManager directly but doing so before the plugin has been - # enabled in settings will throw a compiler error here so I'm using get_singleton instead. - var dialogue_manager = Engine.get_singleton("DialogueManager") - dialogue_manager.dialogue_ended.connect(_on_dialogue_ended) - dialogue_manager.show_dialogue_balloon(resource, title) - - -func _enter_tree() -> void: - DialogueSettings.set_user_value("is_running_test_scene", false) - - -### Signals - - -func _on_dialogue_ended(_resource: DialogueResource): - get_tree().quit() diff --git a/addons/dialogue_manager/test_scene.tscn b/addons/dialogue_manager/test_scene.tscn deleted file mode 100644 index f2bbd8d..0000000 --- a/addons/dialogue_manager/test_scene.tscn +++ /dev/null @@ -1,7 +0,0 @@ -[gd_scene load_steps=2 format=3] - -[ext_resource type="Script" path="res://addons/dialogue_manager/test_scene.gd" id="1_yupoh"] - - -[node name="TestScene" type="Node2D"] -script = ExtResource("1_yupoh") diff --git a/addons/dialogue_manager/utilities/builtins.gd b/addons/dialogue_manager/utilities/builtins.gd deleted file mode 100644 index f8442d4..0000000 --- a/addons/dialogue_manager/utilities/builtins.gd +++ /dev/null @@ -1,468 +0,0 @@ -extends Object - - -const DialogueConstants = preload("../constants.gd") - -const SUPPORTED_BUILTIN_TYPES = [ - TYPE_ARRAY, - TYPE_VECTOR2, - TYPE_VECTOR3, - TYPE_VECTOR4, - TYPE_DICTIONARY, - TYPE_QUATERNION, - TYPE_COLOR, - TYPE_SIGNAL -] - - -static var resolve_method_error: Error = OK - - -static func is_supported(thing) -> bool: - return typeof(thing) in SUPPORTED_BUILTIN_TYPES - - -static func resolve_property(builtin, property: String): - match typeof(builtin): - TYPE_ARRAY, TYPE_DICTIONARY, TYPE_QUATERNION: - return builtin[property] - - # Some types have constants that we need to manually resolve - - TYPE_VECTOR2: - return resolve_vector2_property(builtin, property) - TYPE_VECTOR3: - return resolve_vector3_property(builtin, property) - TYPE_VECTOR4: - return resolve_vector4_property(builtin, property) - TYPE_COLOR: - return resolve_color_property(builtin, property) - - -static func resolve_method(thing, method_name: String, args: Array): - resolve_method_error = OK - - # Resolve static methods manually - match typeof(thing): - TYPE_VECTOR2: - match method_name: - "from_angle": - return Vector2.from_angle(args[0]) - - TYPE_COLOR: - match method_name: - "from_hsv": - return Color.from_hsv(args[0], args[1], args[2]) if args.size() == 3 else Color.from_hsv(args[0], args[1], args[2], args[3]) - "from_ok_hsl": - return Color.from_ok_hsl(args[0], args[1], args[2]) if args.size() == 3 else Color.from_ok_hsl(args[0], args[1], args[2], args[3]) - "from_rgbe9995": - return Color.from_rgbe9995(args[0]) - "from_string": - return Color.from_string(args[0], args[1]) - - TYPE_QUATERNION: - match method_name: - "from_euler": - return Quaternion.from_euler(args[0]) - - # Anything else can be evaulatated automatically - var references: Array = ["thing"] - for i in range(0, args.size()): - references.append("arg%d" % i) - var expression = Expression.new() - if expression.parse("thing.%s(%s)" % [method_name, ",".join(references.slice(1))], references) != OK: - assert(false, expression.get_error_text()) - var result = expression.execute([thing] + args, null, false) - if expression.has_execute_failed(): - resolve_method_error = ERR_CANT_RESOLVE - return null - - return result - - -static func has_resolve_method_failed() -> bool: - return resolve_method_error != OK - - -static func resolve_color_property(color: Color, property: String): - match property: - "ALICE_BLUE": - return Color.ALICE_BLUE - "ANTIQUE_WHITE": - return Color.ANTIQUE_WHITE - "AQUA": - return Color.AQUA - "AQUAMARINE": - return Color.AQUAMARINE - "AZURE": - return Color.AZURE - "BEIGE": - return Color.BEIGE - "BISQUE": - return Color.BISQUE - "BLACK": - return Color.BLACK - "BLANCHED_ALMOND": - return Color.BLANCHED_ALMOND - "BLUE": - return Color.BLUE - "BLUE_VIOLET": - return Color.BLUE_VIOLET - "BROWN": - return Color.BROWN - "BURLYWOOD": - return Color.BURLYWOOD - "CADET_BLUE": - return Color.CADET_BLUE - "CHARTREUSE": - return Color.CHARTREUSE - "CHOCOLATE": - return Color.CHOCOLATE - "CORAL": - return Color.CORAL - "CORNFLOWER_BLUE": - return Color.CORNFLOWER_BLUE - "CORNSILK": - return Color.CORNSILK - "CRIMSON": - return Color.CRIMSON - "CYAN": - return Color.CYAN - "DARK_BLUE": - return Color.DARK_BLUE - "DARK_CYAN": - return Color.DARK_CYAN - "DARK_GOLDENROD": - return Color.DARK_GOLDENROD - "DARK_GRAY": - return Color.DARK_GRAY - "DARK_GREEN": - return Color.DARK_GREEN - "DARK_KHAKI": - return Color.DARK_KHAKI - "DARK_MAGENTA": - return Color.DARK_MAGENTA - "DARK_OLIVE_GREEN": - return Color.DARK_OLIVE_GREEN - "DARK_ORANGE": - return Color.DARK_ORANGE - "DARK_ORCHID": - return Color.DARK_ORCHID - "DARK_RED": - return Color.DARK_RED - "DARK_SALMON": - return Color.DARK_SALMON - "DARK_SEA_GREEN": - return Color.DARK_SEA_GREEN - "DARK_SLATE_BLUE": - return Color.DARK_SLATE_BLUE - "DARK_SLATE_GRAY": - return Color.DARK_SLATE_GRAY - "DARK_TURQUOISE": - return Color.DARK_TURQUOISE - "DARK_VIOLET": - return Color.DARK_VIOLET - "DEEP_PINK": - return Color.DEEP_PINK - "DEEP_SKY_BLUE": - return Color.DEEP_SKY_BLUE - "DIM_GRAY": - return Color.DIM_GRAY - "DODGER_BLUE": - return Color.DODGER_BLUE - "FIREBRICK": - return Color.FIREBRICK - "FLORAL_WHITE": - return Color.FLORAL_WHITE - "FOREST_GREEN": - return Color.FOREST_GREEN - "FUCHSIA": - return Color.FUCHSIA - "GAINSBORO": - return Color.GAINSBORO - "GHOST_WHITE": - return Color.GHOST_WHITE - "GOLD": - return Color.GOLD - "GOLDENROD": - return Color.GOLDENROD - "GRAY": - return Color.GRAY - "GREEN": - return Color.GREEN - "GREEN_YELLOW": - return Color.GREEN_YELLOW - "HONEYDEW": - return Color.HONEYDEW - "HOT_PINK": - return Color.HOT_PINK - "INDIAN_RED": - return Color.INDIAN_RED - "INDIGO": - return Color.INDIGO - "IVORY": - return Color.IVORY - "KHAKI": - return Color.KHAKI - "LAVENDER": - return Color.LAVENDER - "LAVENDER_BLUSH": - return Color.LAVENDER_BLUSH - "LAWN_GREEN": - return Color.LAWN_GREEN - "LEMON_CHIFFON": - return Color.LEMON_CHIFFON - "LIGHT_BLUE": - return Color.LIGHT_BLUE - "LIGHT_CORAL": - return Color.LIGHT_CORAL - "LIGHT_CYAN": - return Color.LIGHT_CYAN - "LIGHT_GOLDENROD": - return Color.LIGHT_GOLDENROD - "LIGHT_GRAY": - return Color.LIGHT_GRAY - "LIGHT_GREEN": - return Color.LIGHT_GREEN - "LIGHT_PINK": - return Color.LIGHT_PINK - "LIGHT_SALMON": - return Color.LIGHT_SALMON - "LIGHT_SEA_GREEN": - return Color.LIGHT_SEA_GREEN - "LIGHT_SKY_BLUE": - return Color.LIGHT_SKY_BLUE - "LIGHT_SLATE_GRAY": - return Color.LIGHT_SLATE_GRAY - "LIGHT_STEEL_BLUE": - return Color.LIGHT_STEEL_BLUE - "LIGHT_YELLOW": - return Color.LIGHT_YELLOW - "LIME": - return Color.LIME - "LIME_GREEN": - return Color.LIME_GREEN - "LINEN": - return Color.LINEN - "MAGENTA": - return Color.MAGENTA - "MAROON": - return Color.MAROON - "MEDIUM_AQUAMARINE": - return Color.MEDIUM_AQUAMARINE - "MEDIUM_BLUE": - return Color.MEDIUM_BLUE - "MEDIUM_ORCHID": - return Color.MEDIUM_ORCHID - "MEDIUM_PURPLE": - return Color.MEDIUM_PURPLE - "MEDIUM_SEA_GREEN": - return Color.MEDIUM_SEA_GREEN - "MEDIUM_SLATE_BLUE": - return Color.MEDIUM_SLATE_BLUE - "MEDIUM_SPRING_GREEN": - return Color.MEDIUM_SPRING_GREEN - "MEDIUM_TURQUOISE": - return Color.MEDIUM_TURQUOISE - "MEDIUM_VIOLET_RED": - return Color.MEDIUM_VIOLET_RED - "MIDNIGHT_BLUE": - return Color.MIDNIGHT_BLUE - "MINT_CREAM": - return Color.MINT_CREAM - "MISTY_ROSE": - return Color.MISTY_ROSE - "MOCCASIN": - return Color.MOCCASIN - "NAVAJO_WHITE": - return Color.NAVAJO_WHITE - "NAVY_BLUE": - return Color.NAVY_BLUE - "OLD_LACE": - return Color.OLD_LACE - "OLIVE": - return Color.OLIVE - "OLIVE_DRAB": - return Color.OLIVE_DRAB - "ORANGE": - return Color.ORANGE - "ORANGE_RED": - return Color.ORANGE_RED - "ORCHID": - return Color.ORCHID - "PALE_GOLDENROD": - return Color.PALE_GOLDENROD - "PALE_GREEN": - return Color.PALE_GREEN - "PALE_TURQUOISE": - return Color.PALE_TURQUOISE - "PALE_VIOLET_RED": - return Color.PALE_VIOLET_RED - "PAPAYA_WHIP": - return Color.PAPAYA_WHIP - "PEACH_PUFF": - return Color.PEACH_PUFF - "PERU": - return Color.PERU - "PINK": - return Color.PINK - "PLUM": - return Color.PLUM - "POWDER_BLUE": - return Color.POWDER_BLUE - "PURPLE": - return Color.PURPLE - "REBECCA_PURPLE": - return Color.REBECCA_PURPLE - "RED": - return Color.RED - "ROSY_BROWN": - return Color.ROSY_BROWN - "ROYAL_BLUE": - return Color.ROYAL_BLUE - "SADDLE_BROWN": - return Color.SADDLE_BROWN - "SALMON": - return Color.SALMON - "SANDY_BROWN": - return Color.SANDY_BROWN - "SEA_GREEN": - return Color.SEA_GREEN - "SEASHELL": - return Color.SEASHELL - "SIENNA": - return Color.SIENNA - "SILVER": - return Color.SILVER - "SKY_BLUE": - return Color.SKY_BLUE - "SLATE_BLUE": - return Color.SLATE_BLUE - "SLATE_GRAY": - return Color.SLATE_GRAY - "SNOW": - return Color.SNOW - "SPRING_GREEN": - return Color.SPRING_GREEN - "STEEL_BLUE": - return Color.STEEL_BLUE - "TAN": - return Color.TAN - "TEAL": - return Color.TEAL - "THISTLE": - return Color.THISTLE - "TOMATO": - return Color.TOMATO - "TRANSPARENT": - return Color.TRANSPARENT - "TURQUOISE": - return Color.TURQUOISE - "VIOLET": - return Color.VIOLET - "WEB_GRAY": - return Color.WEB_GRAY - "WEB_GREEN": - return Color.WEB_GREEN - "WEB_MAROON": - return Color.WEB_MAROON - "WEB_PURPLE": - return Color.WEB_PURPLE - "WHEAT": - return Color.WHEAT - "WHITE": - return Color.WHITE - "WHITE_SMOKE": - return Color.WHITE_SMOKE - "YELLOW": - return Color.YELLOW - "YELLOW_GREEN": - return Color.YELLOW_GREEN - - return color[property] - - -static func resolve_vector2_property(vector: Vector2, property: String): - match property: - "AXIS_X": - return Vector2.AXIS_X - "AXIS_Y": - return Vector2.AXIS_Y - "ZERO": - return Vector2.ZERO - "ONE": - return Vector2.ONE - "INF": - return Vector2.INF - "LEFT": - return Vector2.LEFT - "RIGHT": - return Vector2.RIGHT - "UP": - return Vector2.UP - "DOWN": - return Vector2.DOWN - - return vector[property] - - -static func resolve_vector3_property(vector: Vector3, property: String): - match property: - "AXIS_X": - return Vector3.AXIS_X - "AXIS_Y": - return Vector3.AXIS_Y - "AXIS_Z": - return Vector3.AXIS_Z - "ZERO": - return Vector3.ZERO - "ONE": - return Vector3.ONE - "INF": - return Vector3.INF - "LEFT": - return Vector3.LEFT - "RIGHT": - return Vector3.RIGHT - "UP": - return Vector3.UP - "DOWN": - return Vector3.DOWN - "FORWARD": - return Vector3.FORWARD - "BACK": - return Vector3.BACK - "MODEL_LEFT": - return Vector3(1, 0, 0) - "MODEL_RIGHT": - return Vector3(-1, 0, 0) - "MODEL_TOP": - return Vector3(0, 1, 0) - "MODEL_BOTTOM": - return Vector3(0, -1, 0) - "MODEL_FRONT": - return Vector3(0, 0, 1) - "MODEL_REAR": - return Vector3(0, 0, -1) - - return vector[property] - - -static func resolve_vector4_property(vector: Vector4, property: String): - match property: - "AXIS_X": - return Vector4.AXIS_X - "AXIS_Y": - return Vector4.AXIS_Y - "AXIS_Z": - return Vector4.AXIS_Z - "AXIS_W": - return Vector4.AXIS_W - "ZERO": - return Vector4.ZERO - "ONE": - return Vector4.ONE - "INF": - return Vector4.INF - - return vector[property] diff --git a/addons/dialogue_manager/views/main_view.gd b/addons/dialogue_manager/views/main_view.gd deleted file mode 100644 index 445d53d..0000000 --- a/addons/dialogue_manager/views/main_view.gd +++ /dev/null @@ -1,1100 +0,0 @@ -@tool -extends Control - - -const DialogueConstants = preload("../constants.gd") -const DialogueSettings = preload("../settings.gd") - -const OPEN_OPEN = 100 -const OPEN_CLEAR = 101 - -const TRANSLATIONS_GENERATE_LINE_IDS = 100 -const TRANSLATIONS_SAVE_CHARACTERS_TO_CSV = 201 -const TRANSLATIONS_SAVE_TO_CSV = 202 -const TRANSLATIONS_IMPORT_FROM_CSV = 203 - -const ITEM_SAVE = 100 -const ITEM_SAVE_AS = 101 -const ITEM_CLOSE = 102 -const ITEM_CLOSE_ALL = 103 -const ITEM_CLOSE_OTHERS = 104 -const ITEM_COPY_PATH = 200 -const ITEM_SHOW_IN_FILESYSTEM = 201 - -enum TranslationSource { - CharacterNames, - Lines -} - - -@onready var parse_timer := $ParseTimer - -# Dialogs -@onready var new_dialog: FileDialog = $NewDialog -@onready var save_dialog: FileDialog = $SaveDialog -@onready var open_dialog: FileDialog = $OpenDialog -@onready var export_dialog: FileDialog = $ExportDialog -@onready var import_dialog: FileDialog = $ImportDialog -@onready var errors_dialog: AcceptDialog = $ErrorsDialog -@onready var settings_dialog: AcceptDialog = $SettingsDialog -@onready var settings_view := $SettingsDialog/SettingsView -@onready var build_error_dialog: AcceptDialog = $BuildErrorDialog -@onready var close_confirmation_dialog: ConfirmationDialog = $CloseConfirmationDialog -@onready var updated_dialog: AcceptDialog = $UpdatedDialog -@onready var find_in_files_dialog: AcceptDialog = $FindInFilesDialog -@onready var find_in_files: Control = $FindInFilesDialog/FindInFiles - -# Toolbar -@onready var new_button: Button = %NewButton -@onready var open_button: MenuButton = %OpenButton -@onready var save_all_button: Button = %SaveAllButton -@onready var find_in_files_button: Button = %FindInFilesButton -@onready var test_button: Button = %TestButton -@onready var search_button: Button = %SearchButton -@onready var insert_button: MenuButton = %InsertButton -@onready var translations_button: MenuButton = %TranslationsButton -@onready var settings_button: Button = %SettingsButton -@onready var support_button: Button = %SupportButton -@onready var docs_button: Button = %DocsButton -@onready var version_label: Label = %VersionLabel -@onready var update_button: Button = %UpdateButton - -@onready var search_and_replace := %SearchAndReplace - -# Code editor -@onready var content: HSplitContainer = %Content -@onready var files_list := %FilesList -@onready var files_popup_menu: PopupMenu = %FilesPopupMenu -@onready var title_list := %TitleList -@onready var code_edit := %CodeEdit -@onready var errors_panel := %ErrorsPanel - -# The Dialogue Manager plugin -var editor_plugin: EditorPlugin - -# The currently open file -var current_file_path: String = "": - set(next_current_file_path): - current_file_path = next_current_file_path - files_list.current_file_path = current_file_path - if current_file_path == "": - save_all_button.disabled = true - test_button.disabled = true - search_button.disabled = true - insert_button.disabled = true - translations_button.disabled = true - content.dragger_visibility = SplitContainer.DRAGGER_HIDDEN - files_list.hide() - title_list.hide() - code_edit.hide() - errors_panel.hide() - else: - test_button.disabled = false - search_button.disabled = false - insert_button.disabled = false - translations_button.disabled = false - content.dragger_visibility = SplitContainer.DRAGGER_VISIBLE - files_list.show() - title_list.show() - code_edit.show() - - code_edit.text = open_buffers[current_file_path].text - code_edit.errors = [] - code_edit.clear_undo_history() - code_edit.set_cursor(DialogueSettings.get_caret(current_file_path)) - code_edit.grab_focus() - - _on_code_edit_text_changed() - - errors_panel.errors = [] - code_edit.errors = [] - get: - return current_file_path - -# A reference to the currently open files and their last saved text -var open_buffers: Dictionary = {} - -# Which thing are we exporting translations for? -var translation_source: TranslationSource = TranslationSource.Lines - - -func _ready() -> void: - apply_theme() - - # Start with nothing open - self.current_file_path = "" - - # Set up the update checker - version_label.text = "v%s" % editor_plugin.get_version() - update_button.editor_plugin = editor_plugin - update_button.on_before_refresh = func on_before_refresh(): - # Save everything - DialogueSettings.set_user_value("just_refreshed", { - current_file_path = current_file_path, - open_buffers = open_buffers - }) - return true - - # Did we just load from an addon version refresh? - var just_refreshed = DialogueSettings.get_user_value("just_refreshed", null) - if just_refreshed != null: - DialogueSettings.set_user_value("just_refreshed", null) - call_deferred("load_from_version_refresh", just_refreshed) - - # Hook up the search toolbar - search_and_replace.code_edit = code_edit - - # Connect menu buttons - insert_button.get_popup().id_pressed.connect(_on_insert_button_menu_id_pressed) - translations_button.get_popup().id_pressed.connect(_on_translations_button_menu_id_pressed) - - code_edit.main_view = self - code_edit.wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY if DialogueSettings.get_setting("wrap_lines", false) else TextEdit.LINE_WRAPPING_NONE - var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() - editor_settings.settings_changed.connect(_on_editor_settings_changed) - _on_editor_settings_changed() - - # Reopen any files that were open when Godot was closed - if editor_settings.get_setting("text_editor/behavior/files/restore_scripts_on_load"): - var reopen_files: Array = DialogueSettings.get_user_value("reopen_files", []) - for reopen_file in reopen_files: - open_file(reopen_file) - - self.current_file_path = DialogueSettings.get_user_value("most_recent_reopen_file", "") - - save_all_button.disabled = true - - close_confirmation_dialog.ok_button_text = DialogueConstants.translate(&"confirm_close.save") - close_confirmation_dialog.add_button(DialogueConstants.translate(&"confirm_close.discard"), true, "discard") - - settings_view.editor_plugin = editor_plugin - - errors_dialog.dialog_text = DialogueConstants.translate(&"errors_in_script") - - -func _exit_tree() -> void: - DialogueSettings.set_user_value("reopen_files", open_buffers.keys()) - DialogueSettings.set_user_value("most_recent_reopen_file", self.current_file_path) - - -func _unhandled_input(event: InputEvent) -> void: - if not visible: return - - if event is InputEventKey and event.is_pressed(): - match event.as_text(): - "Ctrl+Alt+S", "Command+Alt+S": - get_viewport().set_input_as_handled() - save_file(current_file_path) - "Ctrl+W", "Command+W": - get_viewport().set_input_as_handled() - close_file(current_file_path) - "Ctrl+F5", "Command+F5": - get_viewport().set_input_as_handled() - _on_test_button_pressed() - "Ctrl+Shift+F", "Command+Shift+F": - get_viewport().set_input_as_handled() - _on_find_in_files_button_pressed() - - -func apply_changes() -> void: - save_files() - - -# Load back to the previous buffer regardless of if it was actually saved -func load_from_version_refresh(just_refreshed: Dictionary) -> void: - if just_refreshed.has("current_file_content"): - # We just loaded from a version before multiple buffers - var file: FileAccess = FileAccess.open(just_refreshed.current_file_path, FileAccess.READ) - var file_text: String = file.get_as_text() - open_buffers[just_refreshed.current_file_path] = { - pristine_text = file_text, - text = just_refreshed.current_file_content - } - else: - open_buffers = just_refreshed.open_buffers - - if just_refreshed.current_file_path != "": - editor_plugin.get_editor_interface().edit_resource(load(just_refreshed.current_file_path)) - else: - editor_plugin.get_editor_interface().set_main_screen_editor("Dialogue") - - updated_dialog.dialog_text = DialogueConstants.translate(&"update.success").format({ version = update_button.get_version() }) - updated_dialog.popup_centered() - - -func new_file(path: String, content: String = "") -> void: - if open_buffers.has(path): - remove_file_from_open_buffers(path) - - var file: FileAccess = FileAccess.open(path, FileAccess.WRITE) - if content == "": - if DialogueSettings.get_setting("new_with_template", true): - file.store_string("\n".join([ - "~ this_is_a_node_title", - "", - "Nathan: [[Hi|Hello|Howdy]], this is some dialogue.", - "Nathan: Here are some choices.", - "- First one", - "\tNathan: You picked the first one.", - "- Second one", - "\tNathan: You picked the second one.", - "- Start again => this_is_a_node_title", - "- End the conversation => END", - "Nathan: For more information see the online documentation.", - "", - "=> END" - ])) - else: - file.store_string(content) - - editor_plugin.get_editor_interface().get_resource_filesystem().scan() - - -# Open a dialogue resource for editing -func open_resource(resource: DialogueResource) -> void: - open_file(resource.resource_path) - - -func open_file(path: String) -> void: - if not open_buffers.has(path): - var file: FileAccess = FileAccess.open(path, FileAccess.READ) - var text = file.get_as_text() - - open_buffers[path] = { - cursor = Vector2.ZERO, - text = text, - pristine_text = text - } - - DialogueSettings.add_recent_file(path) - build_open_menu() - - files_list.files = open_buffers.keys() - files_list.select_file(path) - - self.current_file_path = path - - -func show_file_in_filesystem(path: String) -> void: - var file_system_dock: FileSystemDock = Engine.get_meta("DialogueManagerPlugin") \ - .get_editor_interface() \ - .get_file_system_dock() - - file_system_dock.navigate_to_path(path) - - -# Save any open files -func save_files() -> void: - save_all_button.disabled = true - - var saved_files: PackedStringArray = [] - for path in open_buffers: - if open_buffers[path].text != open_buffers[path].pristine_text: - saved_files.append(path) - save_file(path, false) - - if saved_files.size() > 0: - Engine.get_meta("DialogueCache").reimport_files(saved_files) - - -# Save a file -func save_file(path: String, rescan_file_system: bool = true) -> void: - var buffer = open_buffers[path] - - files_list.mark_file_as_unsaved(path, false) - save_all_button.disabled = files_list.unsaved_files.size() == 0 - - # Don't bother saving if there is nothing to save - if buffer.text == buffer.pristine_text: - return - - buffer.pristine_text = buffer.text - - # Save the current text - var file: FileAccess = FileAccess.open(path, FileAccess.WRITE) - file.store_string(buffer.text) - file.close() - - if rescan_file_system: - Engine.get_meta("DialogueManagerPlugin") \ - .get_editor_interface() \ - .get_resource_filesystem()\ - .scan() - - -func close_file(file: String) -> void: - if not file in open_buffers.keys(): return - - var buffer = open_buffers[file] - - if buffer.text == buffer.pristine_text: - remove_file_from_open_buffers(file) - else: - close_confirmation_dialog.dialog_text = DialogueConstants.translate(&"confirm_close").format({ path = file.get_file() }) - close_confirmation_dialog.popup_centered() - - -func remove_file_from_open_buffers(file: String) -> void: - if not file in open_buffers.keys(): return - - var current_index = open_buffers.keys().find(file) - - open_buffers.erase(file) - if open_buffers.size() == 0: - self.current_file_path = "" - else: - current_index = clamp(current_index, 0, open_buffers.size() - 1) - self.current_file_path = open_buffers.keys()[current_index] - files_list.files = open_buffers.keys() - - -# Apply theme colors and icons to the UI -func apply_theme() -> void: - if is_instance_valid(editor_plugin) and is_instance_valid(code_edit): - var scale: float = editor_plugin.get_editor_interface().get_editor_scale() - var editor_settings = editor_plugin.get_editor_interface().get_editor_settings() - code_edit.theme_overrides = { - scale = scale, - - background_color = editor_settings.get_setting("text_editor/theme/highlighting/background_color"), - current_line_color = editor_settings.get_setting("text_editor/theme/highlighting/current_line_color"), - error_line_color = editor_settings.get_setting("text_editor/theme/highlighting/mark_color"), - - critical_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_markers/critical_color"), - notice_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_markers/notice_color"), - - titles_color = editor_settings.get_setting("text_editor/theme/highlighting/control_flow_keyword_color"), - text_color = editor_settings.get_setting("text_editor/theme/highlighting/text_color"), - conditions_color = editor_settings.get_setting("text_editor/theme/highlighting/keyword_color"), - mutations_color = editor_settings.get_setting("text_editor/theme/highlighting/function_color"), - members_color = editor_settings.get_setting("text_editor/theme/highlighting/member_variable_color"), - strings_color = editor_settings.get_setting("text_editor/theme/highlighting/string_color"), - numbers_color = editor_settings.get_setting("text_editor/theme/highlighting/number_color"), - symbols_color = editor_settings.get_setting("text_editor/theme/highlighting/symbol_color"), - comments_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_color"), - jumps_color = Color(editor_settings.get_setting("text_editor/theme/highlighting/control_flow_keyword_color"), 0.7), - - font_size = editor_settings.get_setting("interface/editor/code_font_size") - } - - new_button.icon = get_theme_icon("New", "EditorIcons") - new_button.tooltip_text = DialogueConstants.translate(&"start_a_new_file") - - open_button.icon = get_theme_icon("Load", "EditorIcons") - open_button.tooltip_text = DialogueConstants.translate(&"open_a_file") - - save_all_button.icon = get_theme_icon("Save", "EditorIcons") - save_all_button.tooltip_text = DialogueConstants.translate(&"start_all_files") - - find_in_files_button.icon = get_theme_icon("ViewportZoom", "EditorIcons") - find_in_files_button.tooltip_text = DialogueConstants.translate(&"find_in_files") - - test_button.icon = get_theme_icon("PlayScene", "EditorIcons") - test_button.tooltip_text = DialogueConstants.translate(&"test_dialogue") - - search_button.icon = get_theme_icon("Search", "EditorIcons") - search_button.tooltip_text = DialogueConstants.translate(&"search_for_text") - - insert_button.icon = get_theme_icon("RichTextEffect", "EditorIcons") - insert_button.text = DialogueConstants.translate(&"insert") - - translations_button.icon = get_theme_icon("Translation", "EditorIcons") - translations_button.text = DialogueConstants.translate(&"translations") - - settings_button.icon = get_theme_icon("Tools", "EditorIcons") - settings_button.tooltip_text = DialogueConstants.translate(&"settings") - - support_button.icon = get_theme_icon("Heart", "EditorIcons") - support_button.text = DialogueConstants.translate(&"sponsor") - support_button.tooltip_text = DialogueConstants.translate(&"show_support") - - docs_button.icon = get_theme_icon("Help", "EditorIcons") - docs_button.text = DialogueConstants.translate(&"docs") - - update_button.apply_theme() - - # Set up the effect menu - var popup: PopupMenu = insert_button.get_popup() - popup.clear() - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.wave_bbcode"), 0) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.shake_bbcode"), 1) - popup.add_separator() - popup.add_icon_item(get_theme_icon("Time", "EditorIcons"), DialogueConstants.translate(&"insert.typing_pause"), 3) - popup.add_icon_item(get_theme_icon("ViewportSpeed", "EditorIcons"), DialogueConstants.translate(&"insert.typing_speed_change"), 4) - popup.add_icon_item(get_theme_icon("DebugNext", "EditorIcons"), DialogueConstants.translate(&"insert.auto_advance"), 5) - popup.add_separator(DialogueConstants.translate(&"insert.templates")) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.title"), 6) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.dialogue"), 7) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.response"), 8) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.random_lines"), 9) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.random_text"), 10) - popup.add_separator(DialogueConstants.translate(&"insert.actions")) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.jump"), 11) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.end_dialogue"), 12) - - # Set up the translations menu - popup = translations_button.get_popup() - popup.clear() - popup.add_icon_item(get_theme_icon("Translation", "EditorIcons"), DialogueConstants.translate(&"generate_line_ids"), TRANSLATIONS_GENERATE_LINE_IDS) - popup.add_separator() - popup.add_icon_item(get_theme_icon("FileList", "EditorIcons"), DialogueConstants.translate(&"save_characters_to_csv"), TRANSLATIONS_SAVE_CHARACTERS_TO_CSV) - popup.add_icon_item(get_theme_icon("FileList", "EditorIcons"), DialogueConstants.translate(&"save_to_csv"), TRANSLATIONS_SAVE_TO_CSV) - popup.add_icon_item(get_theme_icon("AssetLib", "EditorIcons"), DialogueConstants.translate(&"import_from_csv"), TRANSLATIONS_IMPORT_FROM_CSV) - - # Dialog sizes - new_dialog.min_size = Vector2(600, 500) * scale - save_dialog.min_size = Vector2(600, 500) * scale - open_dialog.min_size = Vector2(600, 500) * scale - export_dialog.min_size = Vector2(600, 500) * scale - import_dialog.min_size = Vector2(600, 500) * scale - settings_dialog.min_size = Vector2(1000, 600) * scale - settings_dialog.max_size = Vector2(1000, 600) * scale - find_in_files_dialog.min_size = Vector2(800, 600) * scale - - -### Helpers - - -# Refresh the open menu with the latest files -func build_open_menu() -> void: - var menu = open_button.get_popup() - menu.clear() - menu.add_icon_item(get_theme_icon("Load", "EditorIcons"), DialogueConstants.translate(&"open.open"), OPEN_OPEN) - menu.add_separator() - - var recent_files = DialogueSettings.get_recent_files() - if recent_files.size() == 0: - menu.add_item(DialogueConstants.translate(&"open.no_recent_files")) - menu.set_item_disabled(2, true) - else: - for path in recent_files: - if FileAccess.file_exists(path): - menu.add_icon_item(get_theme_icon("File", "EditorIcons"), path) - - menu.add_separator() - menu.add_item(DialogueConstants.translate(&"open.clear_recent_files"), OPEN_CLEAR) - if menu.id_pressed.is_connected(_on_open_menu_id_pressed): - menu.id_pressed.disconnect(_on_open_menu_id_pressed) - menu.id_pressed.connect(_on_open_menu_id_pressed) - - -# Get the last place a CSV, etc was exported -func get_last_export_path(extension: String) -> String: - var filename = current_file_path.get_file().replace(".dialogue", "." + extension) - return DialogueSettings.get_user_value("last_export_path", current_file_path.get_base_dir()) + "/" + filename - - -# Check the current text for errors -func parse() -> void: - # Skip if nothing to parse - if current_file_path == "": return - - var parser = DialogueManagerParser.new() - var errors: Array[Dictionary] = [] - if parser.parse(code_edit.text, current_file_path) != OK: - errors = parser.get_errors() - code_edit.errors = errors - errors_panel.errors = errors - parser.free() - - -func show_build_error_dialog() -> void: - build_error_dialog.dialog_text = DialogueConstants.translate(&"errors_with_build") - build_error_dialog.popup_centered() - - -# Generate translation line IDs for any line that doesn't already have one -func generate_translations_keys() -> void: - randomize() - seed(Time.get_unix_time_from_system()) - - var parser = DialogueManagerParser.new() - - var cursor: Vector2 = code_edit.get_cursor() - var lines: PackedStringArray = code_edit.text.split("\n") - - var key_regex = RegEx.new() - key_regex.compile("\\[ID:(?<key>.*?)\\]") - - # Make list of known keys - var known_keys = {} - for i in range(0, lines.size()): - var line = lines[i] - var found = key_regex.search(line) - if found: - var text = "" - var l = line.replace(found.strings[0], "").strip_edges().strip_edges() - if l.begins_with("- "): - text = parser.extract_response_prompt(l) - elif ":" in l: - text = l.split(":")[1] - else: - text = l - known_keys[found.strings[found.names.get("key")]] = text - - # Add in any that are missing - for i in lines.size(): - var line = lines[i] - var l = line.strip_edges() - - if parser.is_line_empty(l): continue - if parser.is_condition_line(l, true): continue - if parser.is_title_line(l): continue - if parser.is_mutation_line(l): continue - if parser.is_goto_line(l): continue - if parser.is_import_line(l): continue - - if "[ID:" in line: continue - - var key = "t" + str(randi() % 1000000).sha1_text().substr(0, 10) - while key in known_keys: - key = "t" + str(randi() % 1000000).sha1_text().substr(0, 10) - - var text = "" - if l.begins_with("- "): - text = parser.extract_response_prompt(l) - else: - text = l.substr(l.find(":") + 1) - - lines[i] = line.replace(text, text + " [ID:%s]" % key) - known_keys[key] = text - - code_edit.text = "\n".join(lines) - code_edit.set_cursor(cursor) - _on_code_edit_text_changed() - - parser.free() - - -# Add a translation file to the project settings -func add_path_to_project_translations(path: String) -> void: - var translations: PackedStringArray = ProjectSettings.get_setting("internationalization/locale/translations") - if not path in translations: - translations.append(path) - ProjectSettings.save() - - -# Export dialogue and responses to CSV -func export_translations_to_csv(path: String) -> void: - var default_locale: String = DialogueSettings.get_setting("default_csv_locale", "en") - - var file: FileAccess - - # If the file exists, open it first and work out which keys are already in it - var existing_csv: Dictionary = {} - var column_count: int = 2 - var default_locale_column: int = 1 - var character_column: int = -1 - var notes_column: int = -1 - if FileAccess.file_exists(path): - file = FileAccess.open(path, FileAccess.READ) - var is_first_line = true - var line: Array - while !file.eof_reached(): - line = file.get_csv_line() - if is_first_line: - is_first_line = false - column_count = line.size() - for i in range(1, line.size()): - if line[i] == default_locale: - default_locale_column = i - elif line[i] == "_character": - character_column = i - elif line[i] == "_notes": - notes_column = i - - # Make sure the line isn't empty before adding it - if line.size() > 0 and line[0].strip_edges() != "": - existing_csv[line[0]] = line - - # The character column wasn't found in the existing file but the setting is turned on - if character_column == -1 and DialogueSettings.get_setting("include_character_in_translation_exports", false): - character_column = column_count - column_count += 1 - existing_csv["keys"].append("_character") - - # The notes column wasn't found in the existing file but the setting is turned on - if notes_column == -1 and DialogueSettings.get_setting("include_notes_in_translation_exports", false): - notes_column = column_count - column_count += 1 - existing_csv["keys"].append("_notes") - - # Start a new file - file = FileAccess.open(path, FileAccess.WRITE) - - if not FileAccess.file_exists(path): - var headings: PackedStringArray = ["keys", default_locale] - if DialogueSettings.get_setting("include_character_in_translation_exports", false): - character_column = headings.size() - headings.append("_character") - if DialogueSettings.get_setting("include_notes_in_translation_exports", false): - notes_column = headings.size() - headings.append("_notes") - file.store_csv_line(headings) - column_count = headings.size() - - # Write our translations to file - var known_keys: PackedStringArray = [] - - var dialogue: Dictionary = DialogueManagerParser.parse_string(code_edit.text, current_file_path).lines - - # Make a list of stuff that needs to go into the file - var lines_to_save = [] - for key in dialogue.keys(): - var line: Dictionary = dialogue.get(key) - - if not line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: continue - if line.translation_key in known_keys: continue - - known_keys.append(line.translation_key) - - var line_to_save: PackedStringArray = [] - if existing_csv.has(line.translation_key): - line_to_save = existing_csv.get(line.translation_key) - line_to_save.resize(column_count) - existing_csv.erase(line.translation_key) - else: - line_to_save.resize(column_count) - line_to_save[0] = line.translation_key - - line_to_save[default_locale_column] = line.text - if character_column > -1: - line_to_save[character_column] = "(response)" if line.type == DialogueConstants.TYPE_RESPONSE else line.character - if notes_column > -1: - line_to_save[notes_column] = line.notes - - lines_to_save.append(line_to_save) - - # Store lines in the file, starting with anything that already exists that hasn't been touched - for line in existing_csv.values(): - file.store_csv_line(line) - for line in lines_to_save: - file.store_csv_line(line) - - file.close() - - editor_plugin.get_editor_interface().get_resource_filesystem().scan() - editor_plugin.get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", path) - - # Add it to the project l10n settings if it's not already there - var language_code: RegExMatch = RegEx.create_from_string("^[a-z]{2,3}").search(default_locale) - var translation_path: String = path.replace(".csv", ".%s.translation" % language_code.get_string()) - call_deferred("add_path_to_project_translations", translation_path) - - -func export_character_names_to_csv(path: String) -> void: - var file: FileAccess - - # If the file exists, open it first and work out which keys are already in it - var existing_csv = {} - var commas = [] - if FileAccess.file_exists(path): - file = FileAccess.open(path, FileAccess.READ) - var is_first_line = true - var line: Array - while !file.eof_reached(): - line = file.get_csv_line() - if is_first_line: - is_first_line = false - for i in range(2, line.size()): - commas.append("") - # Make sure the line isn't empty before adding it - if line.size() > 0 and line[0].strip_edges() != "": - existing_csv[line[0]] = line - - # Start a new file - file = FileAccess.open(path, FileAccess.WRITE) - - if not file.file_exists(path): - file.store_csv_line(["keys", DialogueSettings.get_setting("default_csv_locale", "en")]) - - # Write our translations to file - var known_keys: PackedStringArray = [] - - var character_names: PackedStringArray = DialogueManagerParser.parse_string(code_edit.text, current_file_path).character_names - - # Make a list of stuff that needs to go into the file - var lines_to_save = [] - for character_name in character_names: - if character_name in known_keys: continue - - known_keys.append(character_name) - - if existing_csv.has(character_name): - var existing_line = existing_csv.get(character_name) - existing_line[1] = character_name - lines_to_save.append(existing_line) - existing_csv.erase(character_name) - else: - lines_to_save.append(PackedStringArray([character_name, character_name] + commas)) - - # Store lines in the file, starting with anything that already exists that hasn't been touched - for line in existing_csv.values(): - file.store_csv_line(line) - for line in lines_to_save: - file.store_csv_line(line) - - file.close() - - editor_plugin.get_editor_interface().get_resource_filesystem().scan() - editor_plugin.get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", path) - - # Add it to the project l10n settings if it's not already there - var translation_path: String = path.replace(".csv", ".en.translation") - call_deferred("add_path_to_project_translations", translation_path) - - -# Import changes back from an exported CSV by matching translation keys -func import_translations_from_csv(path: String) -> void: - var cursor: Vector2 = code_edit.get_cursor() - - if not FileAccess.file_exists(path): return - - # Open the CSV file and build a dictionary of the known keys - var keys: Dictionary = {} - var file: FileAccess = FileAccess.open(path, FileAccess.READ) - var csv_line: Array - while !file.eof_reached(): - csv_line = file.get_csv_line() - if csv_line.size() > 1: - keys[csv_line[0]] = csv_line[1] - - var parser: DialogueManagerParser = DialogueManagerParser.new() - - # Now look over each line in the dialogue and replace the content for matched keys - var lines: PackedStringArray = code_edit.text.split("\n") - var start_index: int = 0 - var end_index: int = 0 - for i in range(0, lines.size()): - var line: String = lines[i] - var translation_key: String = parser.extract_translation(line) - if keys.has(translation_key): - if parser.is_dialogue_line(line): - start_index = 0 - # See if we need to skip over a character name - line = line.replace("\\:", "!ESCAPED_COLON!") - if ": " in line: - start_index = line.find(": ") + 2 - lines[i] = (line.substr(0, start_index) + keys.get(translation_key) + " [ID:" + translation_key + "]").replace("!ESCAPED_COLON!", ":") - - elif parser.is_response_line(line): - start_index = line.find("- ") + 2 - # See if we need to skip over a character name - line = line.replace("\\:", "!ESCAPED_COLON!") - if ": " in line: - start_index = line.find(": ") + 2 - end_index = line.length() - if " =>" in line: - end_index = line.find(" =>") - if " [if " in line: - end_index = line.find(" [if ") - lines[i] = (line.substr(0, start_index) + keys.get(translation_key) + " [ID:" + translation_key + "]" + line.substr(end_index)).replace("!ESCAPED_COLON!", ":") - - code_edit.text = "\n".join(lines) - code_edit.set_cursor(cursor) - - parser.free() - - -func show_search_form(is_enabled: bool) -> void: - if code_edit.last_selected_text: - search_and_replace.input.text = code_edit.last_selected_text - - search_and_replace.visible = is_enabled - search_button.set_pressed_no_signal(is_enabled) - search_and_replace.focus_line_edit() - - -### Signals - - -func _on_editor_settings_changed() -> void: - var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() - code_edit.minimap_draw = editor_settings.get_setting("text_editor/appearance/minimap/show_minimap") - code_edit.minimap_width = editor_settings.get_setting("text_editor/appearance/minimap/minimap_width") - code_edit.scroll_smooth = editor_settings.get_setting("text_editor/behavior/navigation/smooth_scrolling") - - -func _on_open_menu_id_pressed(id: int) -> void: - match id: - OPEN_OPEN: - open_dialog.popup_centered() - OPEN_CLEAR: - DialogueSettings.clear_recent_files() - build_open_menu() - _: - var menu = open_button.get_popup() - var item = menu.get_item_text(menu.get_item_index(id)) - open_file(item) - - -func _on_files_list_file_selected(file_path: String) -> void: - self.current_file_path = file_path - - -func _on_insert_button_menu_id_pressed(id: int) -> void: - match id: - 0: - code_edit.insert_bbcode("[wave amp=25 freq=5]", "[/wave]") - 1: - code_edit.insert_bbcode("[shake rate=20 level=10]", "[/shake]") - 3: - code_edit.insert_bbcode("[wait=1]") - 4: - code_edit.insert_bbcode("[speed=0.2]") - 5: - code_edit.insert_bbcode("[next=auto]") - 6: - code_edit.insert_text("~ title") - 7: - code_edit.insert_text("Nathan: This is Some Dialogue") - 8: - code_edit.insert_text("Nathan: Choose a Response...\n- Option 1\n\tNathan: You chose option 1\n- Option 2\n\tNathan: You chose option 2") - 9: - code_edit.insert_text("% Nathan: This is random line 1.\n% Nathan: This is random line 2.\n%1 Nathan: This is weighted random line 3.") - 10: - code_edit.insert_text("Nathan: [[Hi|Hello|Howdy]]") - 11: - code_edit.insert_text("=> title") - 12: - code_edit.insert_text("=> END") - - -func _on_translations_button_menu_id_pressed(id: int) -> void: - match id: - TRANSLATIONS_GENERATE_LINE_IDS: - generate_translations_keys() - - TRANSLATIONS_SAVE_CHARACTERS_TO_CSV: - translation_source = TranslationSource.CharacterNames - export_dialog.filters = PackedStringArray(["*.csv ; Translation CSV"]) - export_dialog.current_path = get_last_export_path("csv") - export_dialog.popup_centered() - - TRANSLATIONS_SAVE_TO_CSV: - translation_source = TranslationSource.Lines - export_dialog.filters = PackedStringArray(["*.csv ; Translation CSV"]) - export_dialog.current_path = get_last_export_path("csv") - export_dialog.popup_centered() - - TRANSLATIONS_IMPORT_FROM_CSV: - import_dialog.current_path = get_last_export_path("csv") - import_dialog.popup_centered() - - -func _on_export_dialog_file_selected(path: String) -> void: - DialogueSettings.set_user_value("last_export_path", path.get_base_dir()) - match path.get_extension(): - "csv": - match translation_source: - TranslationSource.CharacterNames: - export_character_names_to_csv(path) - TranslationSource.Lines: - export_translations_to_csv(path) - - -func _on_import_dialog_file_selected(path: String) -> void: - DialogueSettings.set_user_value("last_export_path", path.get_base_dir()) - import_translations_from_csv(path) - - -func _on_main_view_theme_changed(): - apply_theme() - - -func _on_main_view_visibility_changed() -> void: - if visible and is_instance_valid(code_edit): - code_edit.grab_focus() - - -func _on_new_button_pressed() -> void: - new_dialog.current_file = "" - new_dialog.popup_centered() - - -func _on_new_dialog_file_selected(path: String) -> void: - new_file(path) - open_file(path) - - -func _on_save_dialog_file_selected(path: String) -> void: - new_file(path, code_edit.text) - open_file(path) - - -func _on_open_button_about_to_popup() -> void: - build_open_menu() - - -func _on_open_dialog_file_selected(path: String) -> void: - open_file(path) - - -func _on_save_all_button_pressed() -> void: - save_files() - - -func _on_find_in_files_button_pressed() -> void: - find_in_files_dialog.popup_centered() - find_in_files.prepare() - - -func _on_code_edit_text_changed() -> void: - title_list.titles = code_edit.get_titles() - - var buffer = open_buffers[current_file_path] - buffer.text = code_edit.text - - files_list.mark_file_as_unsaved(current_file_path, buffer.text != buffer.pristine_text) - save_all_button.disabled = open_buffers.values().filter(func(d): return d.text != d.pristine_text).size() == 0 - - parse_timer.start(1) - - -func _on_code_edit_active_title_change(title: String) -> void: - title_list.select_title(title) - DialogueSettings.set_user_value("run_title", title) - - -func _on_code_edit_caret_changed() -> void: - DialogueSettings.set_caret(current_file_path, code_edit.get_cursor()) - - -func _on_code_edit_error_clicked(line_number: int) -> void: - errors_panel.show_error_for_line_number(line_number) - - -func _on_title_list_title_selected(title: String) -> void: - code_edit.go_to_title(title) - code_edit.grab_focus() - - -func _on_parse_timer_timeout() -> void: - parse_timer.stop() - parse() - - -func _on_errors_panel_error_pressed(line_number: int, column_number: int) -> void: - code_edit.set_caret_line(line_number) - code_edit.set_caret_column(column_number) - code_edit.grab_focus() - - -func _on_search_button_toggled(button_pressed: bool) -> void: - show_search_form(button_pressed) - - -func _on_search_and_replace_open_requested() -> void: - show_search_form(true) - - -func _on_search_and_replace_close_requested() -> void: - search_button.set_pressed_no_signal(false) - search_and_replace.visible = false - code_edit.grab_focus() - - -func _on_settings_button_pressed() -> void: - settings_view.prepare() - settings_dialog.popup_centered() - - -func _on_settings_view_script_button_pressed(path: String) -> void: - settings_dialog.hide() - editor_plugin.get_editor_interface().edit_resource(load(path)) - - -func _on_test_button_pressed() -> void: - save_file(current_file_path) - - if errors_panel.errors.size() > 0: - errors_dialog.popup_centered() - return - - DialogueSettings.set_user_value("is_running_test_scene", true) - DialogueSettings.set_user_value("run_resource_path", current_file_path) - var test_scene_path: String = DialogueSettings.get_setting("custom_test_scene_path", "res://addons/dialogue_manager/test_scene.tscn") - editor_plugin.get_editor_interface().play_custom_scene(test_scene_path) - - -func _on_settings_dialog_confirmed() -> void: - settings_view.apply_settings_changes() - parse() - code_edit.wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY if DialogueSettings.get_setting("wrap_lines", false) else TextEdit.LINE_WRAPPING_NONE - code_edit.grab_focus() - - -func _on_support_button_pressed() -> void: - OS.shell_open("https://patreon.com/nathanhoad") - - -func _on_docs_button_pressed() -> void: - OS.shell_open("https://github.com/nathanhoad/godot_dialogue_manager") - - -func _on_files_list_file_popup_menu_requested(at_position: Vector2) -> void: - files_popup_menu.position = Vector2(get_viewport().position) + files_list.global_position + at_position - files_popup_menu.popup() - - -func _on_files_list_file_middle_clicked(path: String): - close_file(path) - - -func _on_files_popup_menu_about_to_popup() -> void: - files_popup_menu.clear() - - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save"), ITEM_SAVE, KEY_MASK_CTRL | KEY_MASK_ALT | KEY_S) - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save_as"), ITEM_SAVE_AS) - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close"), ITEM_CLOSE, KEY_MASK_CTRL | KEY_W) - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_all"), ITEM_CLOSE_ALL) - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_other_files"), ITEM_CLOSE_OTHERS) - files_popup_menu.add_separator() - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.copy_file_path"), ITEM_COPY_PATH) - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.show_in_filesystem"), ITEM_SHOW_IN_FILESYSTEM) - - -func _on_files_popup_menu_id_pressed(id: int) -> void: - match id: - ITEM_SAVE: - save_file(current_file_path) - ITEM_SAVE_AS: - save_dialog.popup_centered() - ITEM_CLOSE: - close_file(current_file_path) - ITEM_CLOSE_ALL: - for path in open_buffers.keys(): - close_file(path) - ITEM_CLOSE_OTHERS: - for path in open_buffers.keys(): - if path != current_file_path: - close_file(path) - - ITEM_COPY_PATH: - DisplayServer.clipboard_set(current_file_path) - ITEM_SHOW_IN_FILESYSTEM: - show_file_in_filesystem(current_file_path) - - -func _on_code_edit_external_file_requested(path: String, title: String) -> void: - open_file(path) - if title != "": - code_edit.go_to_title(title) - else: - code_edit.set_caret_line(0) - - -func _on_close_confirmation_dialog_confirmed() -> void: - save_file(current_file_path) - remove_file_from_open_buffers(current_file_path) - - -func _on_close_confirmation_dialog_custom_action(action: StringName) -> void: - if action == "discard": - remove_file_from_open_buffers(current_file_path) - close_confirmation_dialog.hide() - - -func _on_find_in_files_result_selected(path: String, cursor: Vector2, length: int) -> void: - open_file(path) - code_edit.select(cursor.y, cursor.x, cursor.y, cursor.x + length) diff --git a/addons/dialogue_manager/views/main_view.tscn b/addons/dialogue_manager/views/main_view.tscn deleted file mode 100644 index d57bdf9..0000000 --- a/addons/dialogue_manager/views/main_view.tscn +++ /dev/null @@ -1,334 +0,0 @@ -[gd_scene load_steps=14 format=3 uid="uid://cbuf1q3xsse3q"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/views/main_view.gd" id="1_h6qfq"] -[ext_resource type="PackedScene" uid="uid://civ6shmka5e8u" path="res://addons/dialogue_manager/components/code_edit.tscn" id="2_f73fm"] -[ext_resource type="PackedScene" uid="uid://dnufpcdrreva3" path="res://addons/dialogue_manager/components/files_list.tscn" id="2_npj2k"] -[ext_resource type="PackedScene" uid="uid://ctns6ouwwd68i" path="res://addons/dialogue_manager/components/title_list.tscn" id="2_onb4i"] -[ext_resource type="PackedScene" uid="uid://co8yl23idiwbi" path="res://addons/dialogue_manager/components/update_button.tscn" id="2_ph3vs"] -[ext_resource type="PackedScene" uid="uid://gr8nakpbrhby" path="res://addons/dialogue_manager/components/search_and_replace.tscn" id="6_ylh0t"] -[ext_resource type="PackedScene" uid="uid://cs8pwrxr5vxix" path="res://addons/dialogue_manager/components/errors_panel.tscn" id="7_5cvl4"] -[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit_syntax_highlighter.gd" id="7_necsa"] -[ext_resource type="PackedScene" uid="uid://cpg4lg1r3ff6m" path="res://addons/dialogue_manager/views/settings_view.tscn" id="9_8bf36"] -[ext_resource type="PackedScene" uid="uid://0n7hwviyyly4" path="res://addons/dialogue_manager/components/find_in_files.tscn" id="10_yold3"] - -[sub_resource type="Image" id="Image_xvtti"] -data = { -"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), -"format": "RGBA8", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_fguub"] -image = SubResource("Image_xvtti") - -[sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_dvnxt"] -script = ExtResource("7_necsa") - -[node name="MainView" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -script = ExtResource("1_h6qfq") - -[node name="ParseTimer" type="Timer" parent="."] - -[node name="Margin" type="MarginContainer" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_vertical = 3 -theme_override_constants/margin_left = 5 -theme_override_constants/margin_right = 5 -theme_override_constants/margin_bottom = 5 -metadata/_edit_layout_mode = 1 - -[node name="Content" type="HSplitContainer" parent="Margin"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_vertical = 3 -dragger_visibility = 1 - -[node name="SidePanel" type="VBoxContainer" parent="Margin/Content"] -custom_minimum_size = Vector2(150, 0) -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="Toolbar" type="HBoxContainer" parent="Margin/Content/SidePanel"] -layout_mode = 2 - -[node name="NewButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -tooltip_text = "Start a new file" -flat = true - -[node name="OpenButton" type="MenuButton" parent="Margin/Content/SidePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -tooltip_text = "Open a file" - -[node name="SaveAllButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -disabled = true -flat = true - -[node name="FindInFilesButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -flat = true - -[node name="Bookmarks" type="VSplitContainer" parent="Margin/Content/SidePanel"] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="FilesList" parent="Margin/Content/SidePanel/Bookmarks" instance=ExtResource("2_npj2k")] -unique_name_in_owner = true -visible = false -layout_mode = 2 -size_flags_vertical = 3 - -[node name="FilesPopupMenu" type="PopupMenu" parent="Margin/Content/SidePanel/Bookmarks/FilesList"] -unique_name_in_owner = true - -[node name="TitleList" parent="Margin/Content/SidePanel/Bookmarks" instance=ExtResource("2_onb4i")] -unique_name_in_owner = true -visible = false -layout_mode = 2 - -[node name="CodePanel" type="VBoxContainer" parent="Margin/Content"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_stretch_ratio = 4.0 - -[node name="Toolbar" type="HBoxContainer" parent="Margin/Content/CodePanel"] -layout_mode = 2 - -[node name="InsertButton" type="MenuButton" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -disabled = true -text = "Insert" - -[node name="TranslationsButton" type="MenuButton" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -disabled = true -text = "Translations" -item_count = 6 -popup/item_0/text = "Generate line IDs" -popup/item_0/icon = SubResource("ImageTexture_fguub") -popup/item_0/id = 0 -popup/item_1/text = "" -popup/item_1/id = -1 -popup/item_1/separator = true -popup/item_2/text = "Save to CSV..." -popup/item_2/icon = SubResource("ImageTexture_fguub") -popup/item_2/id = 2 -popup/item_3/text = "Import changes from CSV..." -popup/item_3/icon = SubResource("ImageTexture_fguub") -popup/item_3/id = 3 -popup/item_4/text = "" -popup/item_4/id = -1 -popup/item_4/separator = true -popup/item_5/text = "Save to PO..." -popup/item_5/icon = SubResource("ImageTexture_fguub") -popup/item_5/id = 5 - -[node name="Separator" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] -layout_mode = 2 - -[node name="SearchButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -tooltip_text = "Search for text" -disabled = true -toggle_mode = true -flat = true - -[node name="TestButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -tooltip_text = "Test dialogue" -disabled = true -flat = true - -[node name="Separator3" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] -layout_mode = 2 - -[node name="SettingsButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -tooltip_text = "Settings" -flat = true - -[node name="Spacer2" type="Control" parent="Margin/Content/CodePanel/Toolbar"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="SupportButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -flat = true - -[node name="Separator4" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] -layout_mode = 2 - -[node name="DocsButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Docs" -flat = true - -[node name="VersionLabel" type="Label" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -modulate = Color(1, 1, 1, 0.490196) -layout_mode = 2 -text = "v2.19.0" -vertical_alignment = 1 - -[node name="UpdateButton" parent="Margin/Content/CodePanel/Toolbar" instance=ExtResource("2_ph3vs")] -unique_name_in_owner = true -layout_mode = 2 - -[node name="SearchAndReplace" parent="Margin/Content/CodePanel" instance=ExtResource("6_ylh0t")] -unique_name_in_owner = true -layout_mode = 2 - -[node name="CodeEdit" parent="Margin/Content/CodePanel" instance=ExtResource("2_f73fm")] -unique_name_in_owner = true -visible = false -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -theme_override_colors/bookmark_color = Color(1, 0.333333, 0.333333, 1) -text = "" -syntax_highlighter = SubResource("SyntaxHighlighter_dvnxt") - -[node name="ErrorsPanel" parent="Margin/Content/CodePanel" instance=ExtResource("7_5cvl4")] -unique_name_in_owner = true -layout_mode = 2 - -[node name="NewDialog" type="FileDialog" parent="."] -size = Vector2i(600, 500) -min_size = Vector2i(600, 500) -dialog_hide_on_ok = true -filters = PackedStringArray("*.dialogue ; Dialogue") - -[node name="SaveDialog" type="FileDialog" parent="."] -size = Vector2i(600, 500) -min_size = Vector2i(600, 500) -dialog_hide_on_ok = true -filters = PackedStringArray("*.dialogue ; Dialogue") - -[node name="OpenDialog" type="FileDialog" parent="."] -title = "Open a File" -size = Vector2i(600, 500) -min_size = Vector2i(600, 500) -ok_button_text = "Open" -dialog_hide_on_ok = true -file_mode = 0 -filters = PackedStringArray("*.dialogue ; Dialogue") - -[node name="ExportDialog" type="FileDialog" parent="."] -size = Vector2i(600, 500) -min_size = Vector2i(600, 500) - -[node name="ImportDialog" type="FileDialog" parent="."] -title = "Open a File" -size = Vector2i(600, 500) -min_size = Vector2i(600, 500) -ok_button_text = "Open" -file_mode = 0 -filters = PackedStringArray("*.csv ; Translation CSV") - -[node name="ErrorsDialog" type="AcceptDialog" parent="."] -title = "Error" -dialog_text = "You have errors in your script. Fix them and then try again." - -[node name="SettingsDialog" type="AcceptDialog" parent="."] -title = "Settings" -size = Vector2i(834, 600) -unresizable = true -min_size = Vector2i(600, 600) -ok_button_text = "Done" - -[node name="SettingsView" parent="SettingsDialog" instance=ExtResource("9_8bf36")] -offset_left = 8.0 -offset_top = 8.0 -offset_right = -8.0 -offset_bottom = -49.0 - -[node name="BuildErrorDialog" type="AcceptDialog" parent="."] -title = "Errors" -dialog_text = "You need to fix dialogue errors before you can run your game." - -[node name="CloseConfirmationDialog" type="ConfirmationDialog" parent="."] -title = "Unsaved changes" -ok_button_text = "Save changes" - -[node name="UpdatedDialog" type="AcceptDialog" parent="."] -title = "Updated" -size = Vector2i(191, 100) -dialog_text = "You're now up to date!" - -[node name="FindInFilesDialog" type="AcceptDialog" parent="."] -title = "Find in files" -size = Vector2i(416, 457) -ok_button_text = "Done" - -[node name="FindInFiles" parent="FindInFilesDialog" node_paths=PackedStringArray("main_view", "code_edit") instance=ExtResource("10_yold3")] -custom_minimum_size = Vector2(400, 400) -offset_left = 8.0 -offset_top = 8.0 -offset_right = -8.0 -offset_bottom = -49.0 -main_view = NodePath("../..") -code_edit = NodePath("../../Margin/Content/CodePanel/CodeEdit") - -[connection signal="theme_changed" from="." to="." method="_on_main_view_theme_changed"] -[connection signal="visibility_changed" from="." to="." method="_on_main_view_visibility_changed"] -[connection signal="timeout" from="ParseTimer" to="." method="_on_parse_timer_timeout"] -[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/NewButton" to="." method="_on_new_button_pressed"] -[connection signal="about_to_popup" from="Margin/Content/SidePanel/Toolbar/OpenButton" to="." method="_on_open_button_about_to_popup"] -[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/SaveAllButton" to="." method="_on_save_all_button_pressed"] -[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/FindInFilesButton" to="." method="_on_find_in_files_button_pressed"] -[connection signal="file_middle_clicked" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_middle_clicked"] -[connection signal="file_popup_menu_requested" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_popup_menu_requested"] -[connection signal="file_selected" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_selected"] -[connection signal="about_to_popup" from="Margin/Content/SidePanel/Bookmarks/FilesList/FilesPopupMenu" to="." method="_on_files_popup_menu_about_to_popup"] -[connection signal="id_pressed" from="Margin/Content/SidePanel/Bookmarks/FilesList/FilesPopupMenu" to="." method="_on_files_popup_menu_id_pressed"] -[connection signal="title_selected" from="Margin/Content/SidePanel/Bookmarks/TitleList" to="." method="_on_title_list_title_selected"] -[connection signal="toggled" from="Margin/Content/CodePanel/Toolbar/SearchButton" to="." method="_on_search_button_toggled"] -[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/TestButton" to="." method="_on_test_button_pressed"] -[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/SettingsButton" to="." method="_on_settings_button_pressed"] -[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/SupportButton" to="." method="_on_support_button_pressed"] -[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/DocsButton" to="." method="_on_docs_button_pressed"] -[connection signal="close_requested" from="Margin/Content/CodePanel/SearchAndReplace" to="." method="_on_search_and_replace_close_requested"] -[connection signal="open_requested" from="Margin/Content/CodePanel/SearchAndReplace" to="." method="_on_search_and_replace_open_requested"] -[connection signal="active_title_change" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_active_title_change"] -[connection signal="caret_changed" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_caret_changed"] -[connection signal="error_clicked" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_error_clicked"] -[connection signal="external_file_requested" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_external_file_requested"] -[connection signal="text_changed" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_text_changed"] -[connection signal="error_pressed" from="Margin/Content/CodePanel/ErrorsPanel" to="." method="_on_errors_panel_error_pressed"] -[connection signal="file_selected" from="NewDialog" to="." method="_on_new_dialog_file_selected"] -[connection signal="file_selected" from="SaveDialog" to="." method="_on_save_dialog_file_selected"] -[connection signal="file_selected" from="OpenDialog" to="." method="_on_open_dialog_file_selected"] -[connection signal="file_selected" from="ExportDialog" to="." method="_on_export_dialog_file_selected"] -[connection signal="file_selected" from="ImportDialog" to="." method="_on_import_dialog_file_selected"] -[connection signal="confirmed" from="SettingsDialog" to="." method="_on_settings_dialog_confirmed"] -[connection signal="script_button_pressed" from="SettingsDialog/SettingsView" to="." method="_on_settings_view_script_button_pressed"] -[connection signal="confirmed" from="CloseConfirmationDialog" to="." method="_on_close_confirmation_dialog_confirmed"] -[connection signal="custom_action" from="CloseConfirmationDialog" to="." method="_on_close_confirmation_dialog_custom_action"] -[connection signal="result_selected" from="FindInFilesDialog/FindInFiles" to="." method="_on_find_in_files_result_selected"] diff --git a/addons/dialogue_manager/views/settings_view.gd b/addons/dialogue_manager/views/settings_view.gd deleted file mode 100644 index 8ab4e95..0000000 --- a/addons/dialogue_manager/views/settings_view.gd +++ /dev/null @@ -1,280 +0,0 @@ -@tool -extends TabContainer - - -signal script_button_pressed(path: String) - - -const DialogueConstants = preload("../constants.gd") -const DialogueSettings = preload("../settings.gd") - - -enum PathTarget { - CustomTestScene, - Balloon -} - - -# Editor -@onready var new_template_button: CheckBox = $Editor/NewTemplateButton -@onready var characters_translations_button: CheckBox = $Editor/CharactersTranslationsButton -@onready var wrap_lines_button: Button = $Editor/WrapLinesButton -@onready var default_csv_locale: LineEdit = $Editor/DefaultCSVLocale - -# Runtime -@onready var include_all_responses_button: CheckBox = $Runtime/IncludeAllResponsesButton -@onready var ignore_missing_state_values: CheckBox = $Runtime/IgnoreMissingStateValues -@onready var balloon_path_input: LineEdit = $Runtime/CustomBalloon/BalloonPath -@onready var revert_balloon_button: Button = $Runtime/CustomBalloon/RevertBalloonPath -@onready var load_balloon_button: Button = $Runtime/CustomBalloon/LoadBalloonPath -@onready var states_title: Label = $Runtime/StatesTitle -@onready var globals_list: Tree = $Runtime/GlobalsList - -# Advanced -@onready var check_for_updates: CheckBox = $Advanced/CheckForUpdates -@onready var include_characters_in_translations: CheckBox = $Advanced/IncludeCharactersInTranslations -@onready var include_notes_in_translations: CheckBox = $Advanced/IncludeNotesInTranslations -@onready var open_in_external_editor_button: CheckBox = $Advanced/OpenInExternalEditorButton -@onready var test_scene_path_input: LineEdit = $Advanced/CustomTestScene/TestScenePath -@onready var revert_test_scene_button: Button = $Advanced/CustomTestScene/RevertTestScene -@onready var load_test_scene_button: Button = $Advanced/CustomTestScene/LoadTestScene -@onready var custom_test_scene_file_dialog: FileDialog = $CustomTestSceneFileDialog -@onready var create_lines_for_response_characters: CheckBox = $Advanced/CreateLinesForResponseCharacters -@onready var missing_translations_button: CheckBox = $Advanced/MissingTranslationsButton - -var editor_plugin: EditorPlugin -var all_globals: Dictionary = {} -var enabled_globals: Array = [] -var path_target: PathTarget = PathTarget.CustomTestScene - -var _default_test_scene_path: String = preload("../test_scene.tscn").resource_path - -var _recompile_if_changed_settings: Dictionary - - -func _ready() -> void: - new_template_button.text = DialogueConstants.translate(&"settings.new_template") - $Editor/MissingTranslationsHint.text = DialogueConstants.translate(&"settings.missing_keys_hint") - characters_translations_button.text = DialogueConstants.translate(&"settings.characters_translations") - wrap_lines_button.text = DialogueConstants.translate(&"settings.wrap_long_lines") - $Editor/DefaultCSVLocaleLabel.text = DialogueConstants.translate(&"settings.default_csv_locale") - - include_all_responses_button.text = DialogueConstants.translate(&"settings.include_failed_responses") - ignore_missing_state_values.text = DialogueConstants.translate(&"settings.ignore_missing_state_values") - $Runtime/CustomBalloonLabel.text = DialogueConstants.translate(&"settings.default_balloon_hint") - states_title.text = DialogueConstants.translate(&"settings.states_shortcuts") - $Runtime/StatesMessage.text = DialogueConstants.translate(&"settings.states_message") - $Runtime/StatesHint.text = DialogueConstants.translate(&"settings.states_hint") - - check_for_updates.text = DialogueConstants.translate(&"settings.check_for_updates") - include_characters_in_translations.text = DialogueConstants.translate(&"settings.include_characters_in_translations") - include_notes_in_translations.text = DialogueConstants.translate(&"settings.include_notes_in_translations") - open_in_external_editor_button.text = DialogueConstants.translate(&"settings.open_in_external_editor") - $Advanced/ExternalWarning.text = DialogueConstants.translate(&"settings.external_editor_warning") - $Advanced/CustomTestSceneLabel.text = DialogueConstants.translate(&"settings.custom_test_scene") - $Advanced/RecompileWarning.text = DialogueConstants.translate(&"settings.recompile_warning") - missing_translations_button.text = DialogueConstants.translate(&"settings.missing_keys") - create_lines_for_response_characters.text = DialogueConstants.translate(&"settings.create_lines_for_responses_with_characters") - - current_tab = 0 - - -func prepare() -> void: - _recompile_if_changed_settings = _get_settings_that_require_recompilation() - - test_scene_path_input.placeholder_text = DialogueSettings.get_setting("custom_test_scene_path", _default_test_scene_path) - revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path - revert_test_scene_button.icon = get_theme_icon("RotateLeft", "EditorIcons") - revert_test_scene_button.tooltip_text = DialogueConstants.translate(&"settings.revert_to_default_test_scene") - load_test_scene_button.icon = get_theme_icon("Load", "EditorIcons") - - var balloon_path: String = DialogueSettings.get_setting("balloon_path", "") - if not FileAccess.file_exists(balloon_path): - DialogueSettings.set_setting("balloon_path", "") - balloon_path = "" - balloon_path_input.placeholder_text = balloon_path if balloon_path != "" else DialogueConstants.translate(&"settings.default_balloon_path") - revert_balloon_button.visible = balloon_path != "" - revert_balloon_button.icon = get_theme_icon("RotateLeft", "EditorIcons") - revert_balloon_button.tooltip_text = DialogueConstants.translate(&"settings.revert_to_default_balloon") - load_balloon_button.icon = get_theme_icon("Load", "EditorIcons") - - var scale: float = editor_plugin.get_editor_interface().get_editor_scale() - custom_test_scene_file_dialog.min_size = Vector2(600, 500) * scale - - states_title.add_theme_font_override("font", get_theme_font("bold", "EditorFonts")) - - check_for_updates.set_pressed_no_signal(DialogueSettings.get_user_value("check_for_updates", true)) - characters_translations_button.set_pressed_no_signal(DialogueSettings.get_setting("export_characters_in_translation", true)) - wrap_lines_button.set_pressed_no_signal(DialogueSettings.get_setting("wrap_lines", false)) - include_all_responses_button.set_pressed_no_signal(DialogueSettings.get_setting("include_all_responses", false)) - ignore_missing_state_values.set_pressed_no_signal(DialogueSettings.get_setting("ignore_missing_state_values", false)) - new_template_button.set_pressed_no_signal(DialogueSettings.get_setting("new_with_template", true)) - default_csv_locale.text = DialogueSettings.get_setting("default_csv_locale", "en") - - missing_translations_button.set_pressed_no_signal(DialogueSettings.get_setting("missing_translations_are_errors", false)) - create_lines_for_response_characters.set_pressed_no_signal(DialogueSettings.get_setting("create_lines_for_responses_with_characters", true)) - - include_characters_in_translations.set_pressed_no_signal(DialogueSettings.get_setting("include_character_in_translation_exports", false)) - include_notes_in_translations.set_pressed_no_signal(DialogueSettings.get_setting("include_notes_in_translation_exports", false)) - open_in_external_editor_button.set_pressed_no_signal(DialogueSettings.get_user_value("open_in_external_editor", false)) - - var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() - var external_editor: String = editor_settings.get_setting("text_editor/external/exec_path") - var use_external_editor: bool = editor_settings.get_setting("text_editor/external/use_external_editor") and external_editor != "" - if not use_external_editor: - open_in_external_editor_button.hide() - $Advanced/ExternalWarning.hide() - $Advanced/ExternalSeparator.hide() - - var project = ConfigFile.new() - var err = project.load("res://project.godot") - assert(err == OK, "Could not find the project file") - - all_globals.clear() - if project.has_section("autoload"): - for key in project.get_section_keys("autoload"): - if key != "DialogueManager": - all_globals[key] = project.get_value("autoload", key) - - enabled_globals = DialogueSettings.get_setting("states", []).duplicate() - globals_list.clear() - var root = globals_list.create_item() - for name in all_globals.keys(): - var item: TreeItem = globals_list.create_item(root) - item.set_cell_mode(0, TreeItem.CELL_MODE_CHECK) - item.set_checked(0, name in enabled_globals) - item.set_text(0, name) - item.add_button(1, get_theme_icon("Edit", "EditorIcons")) - item.set_text(2, all_globals.get(name, "").replace("*res://", "res://")) - - globals_list.set_column_expand(0, false) - globals_list.set_column_custom_minimum_width(0, 250) - globals_list.set_column_expand(1, false) - globals_list.set_column_custom_minimum_width(1, 40) - globals_list.set_column_titles_visible(true) - globals_list.set_column_title(0, DialogueConstants.translate(&"settings.autoload")) - globals_list.set_column_title(1, "") - globals_list.set_column_title(2, DialogueConstants.translate(&"settings.path")) - - -func apply_settings_changes() -> void: - if _recompile_if_changed_settings != _get_settings_that_require_recompilation(): - Engine.get_meta("DialogueCache").reimport_files() - - -func _get_settings_that_require_recompilation() -> Dictionary: - return DialogueSettings.get_settings([ - "missing_translations_are_errors", - "create_lines_for_responses_with_characters" - ]) - - -### Signals - - -func _on_missing_translations_button_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("missing_translations_are_errors", toggled_on) - - -func _on_characters_translations_button_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("export_characters_in_translation", toggled_on) - - -func _on_wrap_lines_button_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("wrap_lines", toggled_on) - - -func _on_include_all_responses_button_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("include_all_responses", toggled_on) - - -func _on_globals_list_item_selected() -> void: - var item = globals_list.get_selected() - var is_checked = not item.is_checked(0) - item.set_checked(0, is_checked) - - if is_checked: - enabled_globals.append(item.get_text(0)) - else: - enabled_globals.erase(item.get_text(0)) - - DialogueSettings.set_setting("states", enabled_globals) - - -func _on_globals_list_button_clicked(item: TreeItem, column: int, id: int, mouse_button_index: int) -> void: - emit_signal("script_button_pressed", item.get_text(2)) - - -func _on_sample_template_toggled(toggled_on): - DialogueSettings.set_setting("new_with_template", toggled_on) - - -func _on_revert_test_scene_pressed() -> void: - DialogueSettings.set_setting("custom_test_scene_path", _default_test_scene_path) - test_scene_path_input.placeholder_text = _default_test_scene_path - revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path - - -func _on_load_test_scene_pressed() -> void: - path_target = PathTarget.CustomTestScene - custom_test_scene_file_dialog.popup_centered() - - -func _on_custom_test_scene_file_dialog_file_selected(path: String) -> void: - match path_target: - PathTarget.CustomTestScene: - # Check that the test scene is a subclass of BaseDialogueTestScene - var test_scene: PackedScene = load(path) - if test_scene and test_scene.instantiate() is BaseDialogueTestScene: - DialogueSettings.set_setting("custom_test_scene_path", path) - test_scene_path_input.placeholder_text = path - revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path - else: - var accept: AcceptDialog = AcceptDialog.new() - accept.dialog_text = DialogueConstants.translate(&"settings.invalid_test_scene").format({ path = path }) - add_child(accept) - accept.popup_centered.call_deferred() - - PathTarget.Balloon: - DialogueSettings.set_setting("balloon_path", path) - balloon_path_input.placeholder_text = path - revert_balloon_button.visible = balloon_path_input.placeholder_text != "" - - -func _on_ignore_missing_state_values_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("ignore_missing_state_values", toggled_on) - - -func _on_default_csv_locale_text_changed(new_text: String) -> void: - DialogueSettings.set_setting("default_csv_locale", new_text) - - -func _on_revert_balloon_path_pressed() -> void: - DialogueSettings.set_setting("balloon_path", "") - balloon_path_input.placeholder_text = DialogueConstants.translate(&"settings.default_balloon_path") - revert_balloon_button.visible = DialogueSettings.get_setting("balloon_path", "") != "" - - -func _on_load_balloon_path_pressed() -> void: - path_target = PathTarget.Balloon - custom_test_scene_file_dialog.popup_centered() - - -func _on_create_lines_for_response_characters_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("create_lines_for_responses_with_characters", toggled_on) - - -func _on_open_in_external_editor_button_toggled(toggled_on: bool) -> void: - DialogueSettings.set_user_value("open_in_external_editor", toggled_on) - - -func _on_include_characters_in_translations_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("include_character_in_translation_exports", toggled_on) - - -func _on_include_notes_in_translations_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("include_notes_in_translation_exports", toggled_on) - - -func _on_keep_up_to_date_toggled(toggled_on: bool) -> void: - DialogueSettings.set_user_value("check_for_updates", toggled_on) diff --git a/addons/dialogue_manager/views/settings_view.tscn b/addons/dialogue_manager/views/settings_view.tscn deleted file mode 100644 index 09df0a2..0000000 --- a/addons/dialogue_manager/views/settings_view.tscn +++ /dev/null @@ -1,221 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://cpg4lg1r3ff6m"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/views/settings_view.gd" id="1_06uxa"] - -[sub_resource type="Theme" id="Theme_3a8rc"] -HSeparator/constants/separation = 20 - -[node name="SettingsView" type="TabContainer"] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_right = -206.0 -offset_bottom = -345.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -theme = SubResource("Theme_3a8rc") -current_tab = 2 -script = ExtResource("1_06uxa") - -[node name="Editor" type="VBoxContainer" parent="."] -visible = false -layout_mode = 2 - -[node name="NewTemplateButton" type="CheckBox" parent="Editor"] -layout_mode = 2 -button_pressed = true -text = "New dialogue files will start with template text" - -[node name="MissingTranslationsHint" type="Label" parent="Editor"] -modulate = Color(1, 1, 1, 0.501961) -custom_minimum_size = Vector2(10, 0) -layout_mode = 2 -text = "If you are using static translation keys then having this enabled will help you find any lines that you haven't added a key to yet." -autowrap_mode = 3 - -[node name="CharactersTranslationsButton" type="CheckBox" parent="Editor"] -layout_mode = 2 -button_pressed = true -text = "Export character names in translation files" - -[node name="WrapLinesButton" type="CheckBox" parent="Editor"] -layout_mode = 2 -button_pressed = true -text = "Wrap long lines" - -[node name="HSeparator" type="HSeparator" parent="Editor"] -layout_mode = 2 - -[node name="DefaultCSVLocaleLabel" type="Label" parent="Editor"] -layout_mode = 2 -text = "Default CSV Locale" - -[node name="DefaultCSVLocale" type="LineEdit" parent="Editor"] -layout_mode = 2 - -[node name="Runtime" type="VBoxContainer" parent="."] -visible = false -layout_mode = 2 - -[node name="IncludeAllResponsesButton" type="CheckBox" parent="Runtime"] -layout_mode = 2 -text = "Include responses with failed conditions" - -[node name="IgnoreMissingStateValues" type="CheckBox" parent="Runtime"] -layout_mode = 2 -text = "Skip over missing state value errors (not recommended)" - -[node name="HSeparator" type="HSeparator" parent="Runtime"] -layout_mode = 2 - -[node name="CustomBalloonLabel" type="Label" parent="Runtime"] -layout_mode = 2 -text = "Custom balloon to use when calling \"DialogueManager.show_balloon()\"" - -[node name="CustomBalloon" type="HBoxContainer" parent="Runtime"] -layout_mode = 2 - -[node name="BalloonPath" type="LineEdit" parent="Runtime/CustomBalloon"] -layout_mode = 2 -size_flags_horizontal = 3 -focus_mode = 0 -editable = false -shortcut_keys_enabled = false -middle_mouse_paste_enabled = false - -[node name="RevertBalloonPath" type="Button" parent="Runtime/CustomBalloon"] -visible = false -layout_mode = 2 -tooltip_text = "Revert to default test scene" -flat = true - -[node name="LoadBalloonPath" type="Button" parent="Runtime/CustomBalloon"] -layout_mode = 2 - -[node name="HSeparator2" type="HSeparator" parent="Runtime"] -layout_mode = 2 - -[node name="StatesTitle" type="Label" parent="Runtime"] -layout_mode = 2 -text = "State Shortcuts" - -[node name="StatesMessage" type="Label" parent="Runtime"] -layout_mode = 2 -text = "If an autoload is enabled here you can refer to its properties and methods without having to use its name." - -[node name="StatesHint" type="Label" parent="Runtime"] -modulate = Color(1, 1, 1, 0.501961) -custom_minimum_size = Vector2(10, 0) -layout_mode = 2 -text = "ie. Instead of \"SomeState.some_property\" you could just use \"some_property\"" -autowrap_mode = 3 - -[node name="GlobalsList" type="Tree" parent="Runtime"] -layout_mode = 2 -size_flags_vertical = 3 -columns = 3 -column_titles_visible = true -allow_reselect = true -hide_folding = true -hide_root = true -select_mode = 1 - -[node name="Advanced" type="VBoxContainer" parent="."] -layout_mode = 2 - -[node name="CheckForUpdates" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Check for updates" - -[node name="HSeparator" type="HSeparator" parent="Advanced"] -layout_mode = 2 - -[node name="IncludeCharactersInTranslations" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Include character names in translation exports" - -[node name="IncludeNotesInTranslations" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Include notes (## comments) in translation exports" - -[node name="ExternalSeparator" type="HSeparator" parent="Advanced"] -layout_mode = 2 - -[node name="OpenInExternalEditorButton" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Open dialogue files in external editor" - -[node name="ExternalWarning" type="Label" parent="Advanced"] -layout_mode = 2 -text = "Note: Syntax highlighting and detailed error checking are not supported in external editors." - -[node name="HSeparator3" type="HSeparator" parent="Advanced"] -layout_mode = 2 - -[node name="CustomTestSceneLabel" type="Label" parent="Advanced"] -layout_mode = 2 -text = "Custom test scene (must extend BaseDialogueTestScene)" - -[node name="CustomTestScene" type="HBoxContainer" parent="Advanced"] -layout_mode = 2 - -[node name="TestScenePath" type="LineEdit" parent="Advanced/CustomTestScene"] -layout_mode = 2 -size_flags_horizontal = 3 -focus_mode = 0 -placeholder_text = "res://addons/dialogue_manager/test_scene.tscn" -editable = false -shortcut_keys_enabled = false -middle_mouse_paste_enabled = false - -[node name="RevertTestScene" type="Button" parent="Advanced/CustomTestScene"] -visible = false -layout_mode = 2 -tooltip_text = "Revert to default test scene" -flat = true - -[node name="LoadTestScene" type="Button" parent="Advanced/CustomTestScene"] -layout_mode = 2 - -[node name="HSeparator4" type="HSeparator" parent="Advanced"] -layout_mode = 2 - -[node name="RecompileWarning" type="Label" parent="Advanced"] -layout_mode = 2 -text = "Changing these settings will force a recompile of all dialogue. Only change them if you know what you are doing." - -[node name="MissingTranslationsButton" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Treat missing translation keys as errors" - -[node name="CreateLinesForResponseCharacters" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Create child dialogue line for responses with character names in them" - -[node name="CustomTestSceneFileDialog" type="FileDialog" parent="."] -title = "Open a File" -ok_button_text = "Open" -file_mode = 0 -filters = PackedStringArray("*.tscn ; Scene") - -[connection signal="toggled" from="Editor/NewTemplateButton" to="." method="_on_sample_template_toggled"] -[connection signal="toggled" from="Editor/CharactersTranslationsButton" to="." method="_on_characters_translations_button_toggled"] -[connection signal="toggled" from="Editor/WrapLinesButton" to="." method="_on_wrap_lines_button_toggled"] -[connection signal="text_changed" from="Editor/DefaultCSVLocale" to="." method="_on_default_csv_locale_text_changed"] -[connection signal="toggled" from="Runtime/IncludeAllResponsesButton" to="." method="_on_include_all_responses_button_toggled"] -[connection signal="toggled" from="Runtime/IgnoreMissingStateValues" to="." method="_on_ignore_missing_state_values_toggled"] -[connection signal="pressed" from="Runtime/CustomBalloon/RevertBalloonPath" to="." method="_on_revert_balloon_path_pressed"] -[connection signal="pressed" from="Runtime/CustomBalloon/LoadBalloonPath" to="." method="_on_load_balloon_path_pressed"] -[connection signal="button_clicked" from="Runtime/GlobalsList" to="." method="_on_globals_list_button_clicked"] -[connection signal="item_selected" from="Runtime/GlobalsList" to="." method="_on_globals_list_item_selected"] -[connection signal="toggled" from="Advanced/CheckForUpdates" to="." method="_on_keep_up_to_date_toggled"] -[connection signal="toggled" from="Advanced/IncludeCharactersInTranslations" to="." method="_on_include_characters_in_translations_toggled"] -[connection signal="toggled" from="Advanced/IncludeNotesInTranslations" to="." method="_on_include_notes_in_translations_toggled"] -[connection signal="toggled" from="Advanced/OpenInExternalEditorButton" to="." method="_on_open_in_external_editor_button_toggled"] -[connection signal="pressed" from="Advanced/CustomTestScene/RevertTestScene" to="." method="_on_revert_test_scene_pressed"] -[connection signal="pressed" from="Advanced/CustomTestScene/LoadTestScene" to="." method="_on_load_test_scene_pressed"] -[connection signal="toggled" from="Advanced/MissingTranslationsButton" to="." method="_on_missing_translations_button_toggled"] -[connection signal="toggled" from="Advanced/CreateLinesForResponseCharacters" to="." method="_on_create_lines_for_response_characters_toggled"] -[connection signal="file_selected" from="CustomTestSceneFileDialog" to="." method="_on_custom_test_scene_file_dialog_file_selected"] From a5bf94df39dbb7ff706e8d23e430f6623e37dac0 Mon Sep 17 00:00:00 2001 From: JUB-Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 14:30:55 -0400 Subject: [PATCH 24/86] working on maze gdd --- The Maze.md | 66 ---------------------------------------------- src/main/main.tscn | 3 +++ the_maze.md | 31 ++++++++++++++++++++++ 3 files changed, 34 insertions(+), 66 deletions(-) delete mode 100644 The Maze.md create mode 100644 the_maze.md diff --git a/The Maze.md b/The Maze.md deleted file mode 100644 index ceecaf5..0000000 --- a/The Maze.md +++ /dev/null @@ -1,66 +0,0 @@ -# To do -Levels (easy to make) -## puzzle ideas -Every code is unique -combo puzzle (3 or 4 inputs) -missing rooms (you go from 22 to 24 and you're like oh where 23?) -backtracking to solve in another room -giving items to NPCs (you unlock shit from other rooms and give it to other NPCs) -rooms in jumbled order (1 -> 7 -> 12 -> 3) -#### binary type code -1. Binary code history hud -2. Are we expecting the player to know this or do we teach them -3. How do we communicate this to the player -# Ignore everything below -## Main Gameplay loop -Puzzle RPG -interacting with NPCs and using their info to solve puzzles while also fighting enemies using grid movement turn based combat (similar to crypt of the necrodancer) and might have magic spells, might. -## Verbs (mechanics) -Movement before boots -Interacting (z) -Movement after boots: 8 different types of sound 4 of them -move one time the other move a second time -## in the talks -melee combat -### can be scrapped -spells -take off boots -## To Do -## Game -What type of sounds do we want? 8 notes on a scale from a particular sound can be an instrument -How de we translate to the player what the sounds do? Chests tell you? should be done in first room? -How many rooms in total? 6 rooms excluding tutorial room -## Enemies -Cows (Chests hate them cause they moo and smell) -Bees (Chests are scared of them cause they sting) -Chests won't talk to you unless you defeat them -## Rooms -Every room has a chest no matter what -### Tutorial Room -How the song boots work? -### Room 1 -1 cow? -### Room 2 -1 bee? -### Room 3 -1 cow 1 bee? -### Room 4 -1 cow 2 bees? -### Room 5 -lying chests? -### Room 6 (extra room) -you fell for the lying chest -your reward: 2 cows 3 bees -### Spells -stun: stuns enemies -buff: gives you more movement -talk to chest: you talk to chest -## Lore -### All chests have song boots -They see you already have them on so they talk to you -### Why are the chests talking? -Because the developer played souls dark and there was a message with "friend ahead" prompt in front of a mimic and thought that she wanted to be friends with the mimics -### The boots overheat you gonna take em off - -### Why song boots? -The golden piece will give you a way but an unconventional way diff --git a/src/main/main.tscn b/src/main/main.tscn index 0da652a..de4db7b 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -90,3 +90,6 @@ theme_override_colors/font_color = Color(0, 0, 0, 1) theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "B00" + +[node name="Player2" parent="." instance=ExtResource("2_ekt33")] +position = Vector2(130, 47) diff --git a/the_maze.md b/the_maze.md new file mode 100644 index 0000000..fea9ca5 --- /dev/null +++ b/the_maze.md @@ -0,0 +1,31 @@ +# The Maze GDD + +## What is The Maze? +The maze is a non linear narritive puzzle game. + +## Moment to Moment Gameplay +- Navigate rooms +- Talk to NPCs +- Give/Recieve Items +- Enter boot codes + +## Solution concepts +### Songboots +- Use your songboots to enter unique movement based codes. This is the primary puzzle solving method + +#### Codes have unique effects: +- Sending you to a specific or relative room (send to room 10, or to 5 rooms past where you currently are) either immedetly or make stairs that send you there + +- Giving you items, or making items appear somewhere in the Maze + +- There are also Special codes that can only be entered at certain rooms: like a code that lets you enter a number in binary + +### Information from NPCs +- talk to things (people, chests, cows and bees?) and figure out what to do based on that + + + +## puzzle concepts +- missing rooms (you go from 22 to 24 and you're like oh where 23?) +- backtracking to solve in another room +- giving items to NPCs (you unlock shit from other rooms and give it to other NPCs) From 72d14b7f119e0ca2b6011c1fcbe8ff16493ea333 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 15:09:40 -0400 Subject: [PATCH 25/86] wrote out gdd --- the_maze.md | 58 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/the_maze.md b/the_maze.md index fea9ca5..5292ea9 100644 --- a/the_maze.md +++ b/the_maze.md @@ -1,31 +1,49 @@ # The Maze GDD ## What is The Maze? -The maze is a non linear narritive puzzle game. +The maze is a non linear 2d Grid-based narrative puzzle game. +Connect disparate information and piece together not only the secrets of this maze but also a way to escape. ## Moment to Moment Gameplay -- Navigate rooms -- Talk to NPCs -- Give/Recieve Items -- Enter boot codes +- The game is based in screen sized rooms. Go to stairs to travel to another room, the Rooms eventually loop around on themselves. (or maybe getting back to the top requires a movement code?) +- Talk to NPCs in the rooms to learn important information +- Give/Receive Items to/from NPCs and other things in the environment, Players will have a simple inventory with one item equipable at a time. +- Solve puzzles +- Enter boot codes, your movements are recorded, certain movement patterns do things. -## Solution concepts +## Puzzle solving tools ### Songboots -- Use your songboots to enter unique movement based codes. This is the primary puzzle solving method - -#### Codes have unique effects: -- Sending you to a specific or relative room (send to room 10, or to 5 rooms past where you currently are) either immedetly or make stairs that send you there +- Use your Songboots to enter unique movement based codes. Most puzzles will be solved by you figuring out the correct movement code needed +- You can move in 4 cardinal directions, each direction playing a note moving twice in the same direction will play a different note, 8 notes in total, one octave. +#### Code effects: +- Sending you to a specific or relative room (send to room 10, or to 5 rooms past where you currently are) either immediately or make stairs that send you there - Giving you items, or making items appear somewhere in the Maze - -- There are also Special codes that can only be entered at certain rooms: like a code that lets you enter a number in binary +- Codes that can only be entered at certain rooms: like a code that lets you enter a number in binary only when used in a certain room ### Information from NPCs -- talk to things (people, chests, cows and bees?) and figure out what to do based on that - - - -## puzzle concepts -- missing rooms (you go from 22 to 24 and you're like oh where 23?) -- backtracking to solve in another room -- giving items to NPCs (you unlock shit from other rooms and give it to other NPCs) +- Talk to things (people, chests, cows and bees?) and figure out what to do based on that +- Items can be received from NPCs + +#### NPC item types: +- Items that you can give to other NPCs to advance a quest-line +- Items that are temporary or only exist for a limited time (cow's milk that goes bad after a certain number of "mooooves") +- Items that are able to be placed in certain areas (finding a statue and putting a jewel inside it) + + +## Puzzle Ideas we came up with: +- The Maze floors skip over a room (goes from 22 to 24, skipping 23). You need to discover a method of navigation other then going down stairs to be able to travel there. +- Songboot codes delivered though song, with the notes the NPC sings being notes you can play with certain movements +- A logic puzzle with 3 chests, all of them making some accusation about the others lying. Decern which one is telling the truth and open that one + - maybe opening the wrong chests sends you to a random floor? +- Using Items that are findable after the relevant NPC appears, requiring you to wrap around and give it to them +- Chests that are connected? so putting an item inside one will let you retrieve it from another (could be a solution to the milk spoiling idea) +- an NPC who seems to know more then they're letting on sharing secrets about how to navigate the maze (what is their deal) + +## Lore, Story, and Context +### Questions that need to be answered: +- The Maze itself: who what where when why how +- who is the player, what is their goal +- who are the NPCs, what are their goals +- why boots, why sounds +- The golden piece, How should the game end? From 758c1d7ca12037c0b7c492369d5cf6d95202b53d Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 15:30:21 -0400 Subject: [PATCH 26/86] obsidian vault, didn't track any of the hidden files --- docs/the-maze-vault/.gitignore | 1 + docs/the-maze-vault/Welcome.md | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 docs/the-maze-vault/.gitignore create mode 100644 docs/the-maze-vault/Welcome.md diff --git a/docs/the-maze-vault/.gitignore b/docs/the-maze-vault/.gitignore new file mode 100644 index 0000000..1036bd2 --- /dev/null +++ b/docs/the-maze-vault/.gitignore @@ -0,0 +1 @@ +.obsidian/ \ No newline at end of file diff --git a/docs/the-maze-vault/Welcome.md b/docs/the-maze-vault/Welcome.md new file mode 100644 index 0000000..f9bca28 --- /dev/null +++ b/docs/the-maze-vault/Welcome.md @@ -0,0 +1,5 @@ +This is your new *vault*. + +Make a note of something, [[create a link]], or try [the Importer](https://help.obsidian.md/Plugins/Importer)! + +When you're ready, delete this note and make the vault your own. \ No newline at end of file From 544fb8851f55e2b7b2313df8f261ddf67a904786 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 15:32:35 -0400 Subject: [PATCH 27/86] moved gdd to obsidian --- docs/the-maze-vault/design_document.md | 49 ++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 docs/the-maze-vault/design_document.md diff --git a/docs/the-maze-vault/design_document.md b/docs/the-maze-vault/design_document.md new file mode 100644 index 0000000..5292ea9 --- /dev/null +++ b/docs/the-maze-vault/design_document.md @@ -0,0 +1,49 @@ +# The Maze GDD + +## What is The Maze? +The maze is a non linear 2d Grid-based narrative puzzle game. +Connect disparate information and piece together not only the secrets of this maze but also a way to escape. + +## Moment to Moment Gameplay +- The game is based in screen sized rooms. Go to stairs to travel to another room, the Rooms eventually loop around on themselves. (or maybe getting back to the top requires a movement code?) +- Talk to NPCs in the rooms to learn important information +- Give/Receive Items to/from NPCs and other things in the environment, Players will have a simple inventory with one item equipable at a time. +- Solve puzzles +- Enter boot codes, your movements are recorded, certain movement patterns do things. + +## Puzzle solving tools +### Songboots +- Use your Songboots to enter unique movement based codes. Most puzzles will be solved by you figuring out the correct movement code needed +- You can move in 4 cardinal directions, each direction playing a note moving twice in the same direction will play a different note, 8 notes in total, one octave. + +#### Code effects: +- Sending you to a specific or relative room (send to room 10, or to 5 rooms past where you currently are) either immediately or make stairs that send you there +- Giving you items, or making items appear somewhere in the Maze +- Codes that can only be entered at certain rooms: like a code that lets you enter a number in binary only when used in a certain room + +### Information from NPCs +- Talk to things (people, chests, cows and bees?) and figure out what to do based on that +- Items can be received from NPCs + +#### NPC item types: +- Items that you can give to other NPCs to advance a quest-line +- Items that are temporary or only exist for a limited time (cow's milk that goes bad after a certain number of "mooooves") +- Items that are able to be placed in certain areas (finding a statue and putting a jewel inside it) + + +## Puzzle Ideas we came up with: +- The Maze floors skip over a room (goes from 22 to 24, skipping 23). You need to discover a method of navigation other then going down stairs to be able to travel there. +- Songboot codes delivered though song, with the notes the NPC sings being notes you can play with certain movements +- A logic puzzle with 3 chests, all of them making some accusation about the others lying. Decern which one is telling the truth and open that one + - maybe opening the wrong chests sends you to a random floor? +- Using Items that are findable after the relevant NPC appears, requiring you to wrap around and give it to them +- Chests that are connected? so putting an item inside one will let you retrieve it from another (could be a solution to the milk spoiling idea) +- an NPC who seems to know more then they're letting on sharing secrets about how to navigate the maze (what is their deal) + +## Lore, Story, and Context +### Questions that need to be answered: +- The Maze itself: who what where when why how +- who is the player, what is their goal +- who are the NPCs, what are their goals +- why boots, why sounds +- The golden piece, How should the game end? From b11083d8276ad657187385d06386b4b4c3a988af Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 15:33:09 -0400 Subject: [PATCH 28/86] I should review that thing that lets you combine commits --- the_maze.md | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 the_maze.md diff --git a/the_maze.md b/the_maze.md deleted file mode 100644 index 5292ea9..0000000 --- a/the_maze.md +++ /dev/null @@ -1,49 +0,0 @@ -# The Maze GDD - -## What is The Maze? -The maze is a non linear 2d Grid-based narrative puzzle game. -Connect disparate information and piece together not only the secrets of this maze but also a way to escape. - -## Moment to Moment Gameplay -- The game is based in screen sized rooms. Go to stairs to travel to another room, the Rooms eventually loop around on themselves. (or maybe getting back to the top requires a movement code?) -- Talk to NPCs in the rooms to learn important information -- Give/Receive Items to/from NPCs and other things in the environment, Players will have a simple inventory with one item equipable at a time. -- Solve puzzles -- Enter boot codes, your movements are recorded, certain movement patterns do things. - -## Puzzle solving tools -### Songboots -- Use your Songboots to enter unique movement based codes. Most puzzles will be solved by you figuring out the correct movement code needed -- You can move in 4 cardinal directions, each direction playing a note moving twice in the same direction will play a different note, 8 notes in total, one octave. - -#### Code effects: -- Sending you to a specific or relative room (send to room 10, or to 5 rooms past where you currently are) either immediately or make stairs that send you there -- Giving you items, or making items appear somewhere in the Maze -- Codes that can only be entered at certain rooms: like a code that lets you enter a number in binary only when used in a certain room - -### Information from NPCs -- Talk to things (people, chests, cows and bees?) and figure out what to do based on that -- Items can be received from NPCs - -#### NPC item types: -- Items that you can give to other NPCs to advance a quest-line -- Items that are temporary or only exist for a limited time (cow's milk that goes bad after a certain number of "mooooves") -- Items that are able to be placed in certain areas (finding a statue and putting a jewel inside it) - - -## Puzzle Ideas we came up with: -- The Maze floors skip over a room (goes from 22 to 24, skipping 23). You need to discover a method of navigation other then going down stairs to be able to travel there. -- Songboot codes delivered though song, with the notes the NPC sings being notes you can play with certain movements -- A logic puzzle with 3 chests, all of them making some accusation about the others lying. Decern which one is telling the truth and open that one - - maybe opening the wrong chests sends you to a random floor? -- Using Items that are findable after the relevant NPC appears, requiring you to wrap around and give it to them -- Chests that are connected? so putting an item inside one will let you retrieve it from another (could be a solution to the milk spoiling idea) -- an NPC who seems to know more then they're letting on sharing secrets about how to navigate the maze (what is their deal) - -## Lore, Story, and Context -### Questions that need to be answered: -- The Maze itself: who what where when why how -- who is the player, what is their goal -- who are the NPCs, what are their goals -- why boots, why sounds -- The golden piece, How should the game end? From d6cdc5594a412e27b7fcbe8e9c096e9789d8c9f3 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 15:49:28 -0400 Subject: [PATCH 29/86] added a rule --- docs/the-maze-vault/valut_rules.md.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docs/the-maze-vault/valut_rules.md.md diff --git a/docs/the-maze-vault/valut_rules.md.md b/docs/the-maze-vault/valut_rules.md.md new file mode 100644 index 0000000..a0eace0 --- /dev/null +++ b/docs/the-maze-vault/valut_rules.md.md @@ -0,0 +1,2 @@ +# rules to keep the vault clean +- please keep all file names snake_case \ No newline at end of file From 1f2d522ffaa840ac0d2583bb3b2961bee82c91d0 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 19:53:20 -0400 Subject: [PATCH 30/86] item database and resources --- assets/dialogue_boxes/balloon.gd | 141 ++++++++++++++++++++++ assets/dialogue_boxes/balloon.tscn | 176 ++++++++++++++++++++++++++++ assets/dialogue_boxes/balloon2.tscn | 176 ++++++++++++++++++++++++++++ assets/equipped-icon.png | Bin 0 -> 162 bytes assets/equipped-icon.png.import | 34 ++++++ assets/item_icons/x.png | Bin 0 -> 201 bytes assets/item_icons/x.png.import | 34 ++++++ assets/ui_themes/new_theme.tres | 16 +++ project.godot | 17 ++- src/autoloads/player_state.gd | 18 +-- src/items/item_db.gd | 29 +++++ src/items/item_res.gd | 14 +++ src/items/test_item.tres | 9 ++ src/main/main.tscn | 74 ++++++++++-- src/main/ui.gd | 6 +- src/player/player.gd | 2 +- src/scene-tiles/chest/chest.gd | 7 +- todo.md | 17 +++ 18 files changed, 742 insertions(+), 28 deletions(-) create mode 100644 assets/dialogue_boxes/balloon.gd create mode 100644 assets/dialogue_boxes/balloon.tscn create mode 100644 assets/dialogue_boxes/balloon2.tscn create mode 100644 assets/equipped-icon.png create mode 100644 assets/equipped-icon.png.import create mode 100644 assets/item_icons/x.png create mode 100644 assets/item_icons/x.png.import create mode 100644 assets/ui_themes/new_theme.tres create mode 100644 src/items/item_db.gd create mode 100644 src/items/item_res.gd create mode 100644 src/items/test_item.tres create mode 100644 todo.md diff --git a/assets/dialogue_boxes/balloon.gd b/assets/dialogue_boxes/balloon.gd new file mode 100644 index 0000000..875e52f --- /dev/null +++ b/assets/dialogue_boxes/balloon.gd @@ -0,0 +1,141 @@ +extends CanvasLayer + +## 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" + +@onready var balloon: Control = %Balloon +@onready var character_label: RichTextLabel = %CharacterLabel +@onready var dialogue_label: DialogueLabel = %DialogueLabel +@onready var responses_menu: DialogueResponsesMenu = %ResponsesMenu + +## 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 + +## The current line +var dialogue_line: DialogueLine: + set(next_dialogue_line): + is_waiting_for_input = false + balloon.focus_mode = Control.FOCUS_ALL + balloon.grab_focus() + + # The dialogue has finished so close the balloon + if not next_dialogue_line: + queue_free() + return + + # If the node isn't ready yet then none of the labels will be ready yet either + if not is_node_ready(): + await ready + + dialogue_line = next_dialogue_line + + 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.set_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() + get: + return dialogue_line + + +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 + + +func _unhandled_input(_event: InputEvent) -> void: + # Only the balloon is allowed to handle input while it's showing + get_viewport().set_input_as_handled() + + +## 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) + + +## 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) + + +### Signals + + +func _on_mutated(_mutation: Dictionary) -> void: + is_waiting_for_input = false + will_hide_balloon = true + get_tree().create_timer(0.1).timeout.connect(func(): + if will_hide_balloon: + will_hide_balloon = false + balloon.hide() + ) + + +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 _on_responses_menu_response_selected(response: DialogueResponse) -> void: + next(response.next_id) diff --git a/assets/dialogue_boxes/balloon.tscn b/assets/dialogue_boxes/balloon.tscn new file mode 100644 index 0000000..8f8f106 --- /dev/null +++ b/assets/dialogue_boxes/balloon.tscn @@ -0,0 +1,176 @@ +[gd_scene load_steps=11 format=3 uid="uid://13s5spsk34qu"] + +[ext_resource type="Script" path="res://assets/dialogue_boxes/balloon.gd" id="1_s2gbs"] +[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_hfvdi"] +[ext_resource type="Theme" uid="uid://eyq5i2mlpkwn" path="res://assets/ui_themes/new_theme.tres" id="2_ui2vm"] +[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_menu.gd" id="3_1j1j0"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_235ry"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.345098, 0.345098, 0.345098, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ufjut"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.227451, 0.227451, 0.227451, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(1, 1, 1, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fcbqo"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_t6i7a"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uy0d5"] +bg_color = Color(0, 0, 0, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="Theme" id="Theme_qq3yp"] +default_font_size = 8 +Button/styles/disabled = SubResource("StyleBoxFlat_235ry") +Button/styles/focus = SubResource("StyleBoxFlat_ufjut") +Button/styles/hover = SubResource("StyleBoxFlat_fcbqo") +Button/styles/normal = SubResource("StyleBoxFlat_t6i7a") +MarginContainer/constants/margin_bottom = 4 +MarginContainer/constants/margin_left = 8 +MarginContainer/constants/margin_right = 8 +MarginContainer/constants/margin_top = 4 +Panel/styles/panel = SubResource("StyleBoxFlat_uy0d5") + +[node name="ExampleBalloon" type="CanvasLayer"] +layer = 100 +script = ExtResource("1_s2gbs") +next_action = &"adv_txt" +skip_action = &"cancel_txt" + +[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"] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 1.0 +offset_top = -43.0 +grow_horizontal = 2 +grow_vertical = 0 +theme = ExtResource("2_ui2vm") + +[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 +theme = ExtResource("2_ui2vm") + +[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.498039) +layout_mode = 2 +mouse_filter = 1 +bbcode_enabled = true +text = "Character" +fit_content = true +scroll_active = false + +[node name="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("2_hfvdi")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +text = "Dialogue..." + +[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 = -124.0 +offset_top = -218.0 +offset_right = 125.0 +offset_bottom = -50.0 +grow_horizontal = 2 +grow_vertical = 0 +theme = ExtResource("2_ui2vm") + +[node name="ResponsesMenu" type="VBoxContainer" parent="Balloon/Responses"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 8 +theme_override_constants/separation = 2 +script = ExtResource("3_1j1j0") + +[node name="ResponseExample" type="Button" parent="Balloon/Responses/ResponsesMenu"] +layout_mode = 2 +text = "Response Example" + +[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"] diff --git a/assets/dialogue_boxes/balloon2.tscn b/assets/dialogue_boxes/balloon2.tscn new file mode 100644 index 0000000..18be933 --- /dev/null +++ b/assets/dialogue_boxes/balloon2.tscn @@ -0,0 +1,176 @@ +[gd_scene load_steps=11 format=3 uid="uid://blwpjecivsqli"] + +[ext_resource type="Script" path="res://assets/dialogue_boxes/balloon.gd" id="1_wmucd"] +[ext_resource type="Theme" uid="uid://eyq5i2mlpkwn" path="res://assets/ui_themes/new_theme.tres" id="2_i6ssm"] +[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="3_np1qn"] +[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_menu.gd" id="4_qcru4"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_235ry"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.345098, 0.345098, 0.345098, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ufjut"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.227451, 0.227451, 0.227451, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(1, 1, 1, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fcbqo"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_t6i7a"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uy0d5"] +bg_color = Color(0, 0, 0, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="Theme" id="Theme_qq3yp"] +default_font_size = 8 +Button/styles/disabled = SubResource("StyleBoxFlat_235ry") +Button/styles/focus = SubResource("StyleBoxFlat_ufjut") +Button/styles/hover = SubResource("StyleBoxFlat_fcbqo") +Button/styles/normal = SubResource("StyleBoxFlat_t6i7a") +MarginContainer/constants/margin_bottom = 4 +MarginContainer/constants/margin_left = 8 +MarginContainer/constants/margin_right = 8 +MarginContainer/constants/margin_top = 4 +Panel/styles/panel = SubResource("StyleBoxFlat_uy0d5") + +[node name="ExampleBalloon" type="CanvasLayer"] +layer = 100 +script = ExtResource("1_wmucd") + +[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"] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 3.0 +offset_top = -62.0 +offset_right = -4.0 +offset_bottom = -4.0 +grow_horizontal = 2 +grow_vertical = 0 +theme = ExtResource("2_i6ssm") + +[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 +theme = ExtResource("2_i6ssm") + +[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.498039) +layout_mode = 2 +mouse_filter = 1 +bbcode_enabled = true +text = "Character" +fit_content = true +scroll_active = false + +[node name="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("3_np1qn")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +text = "Dialogue..." + +[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 = -124.0 +offset_top = -218.0 +offset_right = 125.0 +offset_bottom = -50.0 +grow_horizontal = 2 +grow_vertical = 0 +theme = ExtResource("2_i6ssm") + +[node name="ResponsesMenu" type="VBoxContainer" parent="Balloon/Responses"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 8 +theme_override_constants/separation = 2 +script = ExtResource("4_qcru4") + +[node name="ResponseExample" type="Button" parent="Balloon/Responses/ResponsesMenu"] +layout_mode = 2 +text = "Response Example" + +[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"] diff --git a/assets/equipped-icon.png b/assets/equipped-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b9f726eb34ad332c9d4ccf2a8c8203f2cfc241fd GIT binary patch literal 162 zcmeAS@N?(olHy`uVBq!ia0vp^20$#p!3HD)*8SNCq!^2X+?^QKos)S9<ivQoIEHw1 zzP-GWk3oQkB|!b(|LNI=3a*cM)_&=2R|^T|YHYF;5R^1yxNz;)oTFFHu6EjeX40D0 zjIj2&eRk3QdmGeUx!2aup7)zC=4^v%ec6L2UwaI`-YHjL31WTZs35g*8E-bw9tKZW KKbLh*2~7Y7Ogbb0 literal 0 HcmV?d00001 diff --git a/assets/equipped-icon.png.import b/assets/equipped-icon.png.import new file mode 100644 index 0000000..d0aaae3 --- /dev/null +++ b/assets/equipped-icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c7retsmbiaoy4" +path="res://.godot/imported/equipped-icon.png-e310f1f9d8d71994fb85fb03a818c6b7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/equipped-icon.png" +dest_files=["res://.godot/imported/equipped-icon.png-e310f1f9d8d71994fb85fb03a818c6b7.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 diff --git a/assets/item_icons/x.png b/assets/item_icons/x.png new file mode 100644 index 0000000000000000000000000000000000000000..36598307451b577b14dd7cfd3f257a15bcba5a5d GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|nmt_{Lo9md zPCm_hK!L}3?mOn+?<Y2%S{jmB=XRF&#AX>DhKApoGSl9Q^LKR^+*qf7?ZCMuHU)m0 z<U(6Zc%zpz#j~q_Gp;x%so&EXVPTP=B*!*MBqGwH^nlxkmw$G-XkR+EBV8_eijv85 z+v2Z&hvH8>IG5_Nuxahv^YcRAJvh_3Dv5D+R{hh62!0u$a~M2b{an^LB{Ts5;M7g% literal 0 HcmV?d00001 diff --git a/assets/item_icons/x.png.import b/assets/item_icons/x.png.import new file mode 100644 index 0000000..9bea815 --- /dev/null +++ b/assets/item_icons/x.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bk51v1m1wfhex" +path="res://.godot/imported/x.png-3ec7665c51167d707c62ab68705ebe01.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/item_icons/x.png" +dest_files=["res://.godot/imported/x.png-3ec7665c51167d707c62ab68705ebe01.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 diff --git a/assets/ui_themes/new_theme.tres b/assets/ui_themes/new_theme.tres new file mode 100644 index 0000000..6bc4691 --- /dev/null +++ b/assets/ui_themes/new_theme.tres @@ -0,0 +1,16 @@ +[gd_resource type="Theme" load_steps=3 format=3 uid="uid://eyq5i2mlpkwn"] + +[ext_resource type="FontFile" uid="uid://ddjw625xpmwtc" path="res://assets/Not Jam UI Condensed 16.ttf" id="1_eoag7"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_h7nxl"] +bg_color = Color(0.301961, 0.301961, 0.301961, 1) +border_width_left = 2 +border_width_top = 2 +border_width_right = 2 +border_width_bottom = 2 +border_color = Color(1, 1, 1, 1) + +[resource] +default_font = ExtResource("1_eoag7") +default_font_size = 16 +Panel/styles/panel = SubResource("StyleBoxFlat_h7nxl") diff --git a/project.godot b/project.godot index 0c34852..95c1d12 100644 --- a/project.godot +++ b/project.godot @@ -19,6 +19,11 @@ config/icon="res://icon.svg" DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd" PlayerState="res://src/autoloads/player_state.gd" +ItemDb="*res://src/items/item_db.gd" + +[dialogue_manager] + +general/balloon_path="res://assets/dialogue_boxes/balloon.tscn" [display] @@ -54,11 +59,21 @@ interact={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) ] } -adv_text={ +adv_txt={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) ] } +cancel_txt={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":88,"key_label":0,"unicode":120,"echo":false,"script":null) +] +} +inventory={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":99,"echo":false,"script":null) +] +} [internationalization] diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd index ed93a91..684b731 100644 --- a/src/autoloads/player_state.gd +++ b/src/autoloads/player_state.gd @@ -3,19 +3,19 @@ extends Node # these are functions that can be called in the dialog system func has_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - return player.has_boots + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + return player.has_boots func _give_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - player.give_boots() - var ui = current_scene.get_node("UI") - ui.bootIcon.visible = true + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + player.give_boots() + var ui = current_scene.get_node("UI") + ui.bootIcon.visible = true # ion know what this returns func _get_current_scene(): - return get_tree().get_root().get_children()[2] \ No newline at end of file + return get_tree().get_root().get_children()[2] diff --git a/src/items/item_db.gd b/src/items/item_db.gd new file mode 100644 index 0000000..4af0963 --- /dev/null +++ b/src/items/item_db.gd @@ -0,0 +1,29 @@ +extends Resource + +#currently auto-loaded, although I think we could get away with it being a static script, as it dosen't have any instanced values we need to maintain, + + +const ITEMS = { + 0:{ + "id_name":"test_item", + "title": "Test Item", + "icon":"x.png", + "description":"You shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden." + }, + 1:{ + "name":"test_item1", + "title": "Another Test Item", + "icon":"x.png", + "description":"You (also) shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden." + } +} + +# item constructor +func give_item(id:int) -> void: + var new_item:Item = Item.new() + new_item.id_name = ITEMS[id]["name"] + new_item.title = ITEMS[id]["title"] + new_item.icon = ITEMS[id]["icon"] + new_item.description = ITEMS[id]["description"] + # add resource to player inventory + diff --git a/src/items/item_res.gd b/src/items/item_res.gd new file mode 100644 index 0000000..10ffba7 --- /dev/null +++ b/src/items/item_res.gd @@ -0,0 +1,14 @@ +class_name Item +extends Resource + +var icon:Texture +var id_name:String +var title:String +var description:String +var in_inventory = false + +func given_to_player(): + in_inventory = true + +func removed_from_player(): + in_inventory = false \ No newline at end of file diff --git a/src/items/test_item.tres b/src/items/test_item.tres new file mode 100644 index 0000000..4e0fa23 --- /dev/null +++ b/src/items/test_item.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="Item" load_steps=2 format=3 uid="uid://c5ru2507ecm8f"] + +[ext_resource type="Script" path="res://src/items/item.gd" id="1_b1mog"] + +[resource] +script = ExtResource("1_b1mog") +id = 0 +ui_name = "" +description = "" diff --git a/src/main/main.tscn b/src/main/main.tscn index de4db7b..cb0cca0 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=8 format=3 uid="uid://cv5xm6ru2dkxf"] +[gd_scene load_steps=10 format=3 uid="uid://cv5xm6ru2dkxf"] [ext_resource type="Script" path="res://src/main/main.gd" id="1_8hq0w"] [ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] @@ -7,9 +7,12 @@ [ext_resource type="Script" path="res://src/main/ui.gd" id="4_o4xue"] [ext_resource type="Texture2D" uid="uid://5kstmna3yb6t" path="res://assets/white.png" id="6_8laen"] [ext_resource type="FontFile" uid="uid://ddjw625xpmwtc" path="res://assets/Not Jam UI Condensed 16.ttf" id="6_sa7lc"] +[ext_resource type="Texture2D" uid="uid://c7retsmbiaoy4" path="res://assets/equipped-icon.png" id="8_h4ayj"] +[ext_resource type="Theme" uid="uid://eyq5i2mlpkwn" path="res://assets/ui_themes/new_theme.tres" id="8_xwmxw"] [node name="Main" type="Node2D"] script = ExtResource("1_8hq0w") +metadata/_edit_vertical_guides_ = [128.0] [node name="Player" parent="." instance=ExtResource("2_ekt33")] position = Vector2(80, 48) @@ -48,14 +51,20 @@ offset_bottom = 16.0 [node name="Bar" type="TextureRect" parent="UI/HUD"] layout_mode = 2 -offset_right = 256.0 +offset_left = 1.0 +offset_right = 257.0 offset_bottom = 17.0 texture = ExtResource("6_8laen") -[node name="BootIcon" type="Sprite2D" parent="UI/HUD"] -visible = false -modulate = Color(0, 0, 0, 1) -position = Vector2(160, 0) +[node name="EquippedWrapper" type="Sprite2D" parent="UI/HUD"] +modulate = Color(0.301961, 0.301961, 0.301961, 1) +position = Vector2(144, 0) +texture = ExtResource("8_h4ayj") +centered = false +region_rect = Rect2(640, 16, 16, 16) + +[node name="EquippedItem" type="Sprite2D" parent="UI/HUD/EquippedWrapper"] +position = Vector2(16, 0) texture = ExtResource("1_kghfi") centered = false region_enabled = true @@ -66,30 +75,69 @@ layout_mode = 2 offset_left = 16.0 offset_right = 54.0 offset_bottom = 16.0 -theme_override_colors/font_color = Color(0, 0, 0, 1) +theme = ExtResource("8_xwmxw") +theme_override_colors/font_color = Color(0.301961, 0.301961, 0.301961, 1) theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "HP: 3/3" -[node name="HPLabel2" type="Label" parent="UI/HUD"] +[node name="Gold Label" type="Label" parent="UI/HUD"] layout_mode = 2 offset_left = 192.0 offset_right = 206.0 offset_bottom = 16.0 -theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_color = Color(0.301961, 0.301961, 0.301961, 1) theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "0g" -[node name="HPLabel3" type="Label" parent="UI/HUD"] +[node name="FloorLabel" type="Label" parent="UI/HUD"] layout_mode = 2 offset_left = 224.0 offset_right = 262.0 offset_bottom = 16.0 -theme_override_colors/font_color = Color(0, 0, 0, 1) +theme = ExtResource("8_xwmxw") +theme_override_colors/font_color = Color(0.301961, 0.301961, 0.301961, 1) theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "B00" -[node name="Player2" parent="." instance=ExtResource("2_ekt33")] -position = Vector2(130, 47) +[node name="CanvasLayer" type="CanvasLayer" parent="."] +visible = false + +[node name="Menu" type="Control" parent="CanvasLayer"] +layout_mode = 3 +anchors_preset = 0 +offset_top = 17.0 +offset_right = 256.0 +offset_bottom = 144.0 + +[node name="Panel" type="Panel" parent="CanvasLayer/Menu"] +layout_mode = 0 +offset_right = 256.0 +offset_bottom = 127.0 +theme = ExtResource("8_xwmxw") + +[node name="VBoxRight" type="VBoxContainer" parent="CanvasLayer/Menu/Panel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = -128.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Panel2" type="Panel" parent="CanvasLayer/Menu"] +layout_mode = 0 +offset_left = 128.0 +offset_right = 256.0 +offset_bottom = 127.0 +theme = ExtResource("8_xwmxw") + +[node name="VBoxLeft" type="VBoxContainer" parent="CanvasLayer/Menu/Panel2"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/src/main/ui.gd b/src/main/ui.gd index a7c02d2..3d7e455 100644 --- a/src/main/ui.gd +++ b/src/main/ui.gd @@ -22,7 +22,7 @@ func render_text(new_text_arr) -> void: textbox.visible = false text_removed.emit() -func _input(event: InputEvent) -> void: - if event.is_action_pressed("adv_text"): - text_advanced.emit() +#func _input(event: InputEvent) -> void: + #if event.is_action_pressed("adv_text"): + #text_advanced.emit() diff --git a/src/player/player.gd b/src/player/player.gd index c744812..d3e5105 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -39,7 +39,7 @@ func _unhandled_input(event: InputEvent) -> void: if _input_dir != Vector2.ZERO: _move(_input_dir) return - if event.is_action_pressed('ui_accept'): + if event.is_action_pressed('interact'): _interact() diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 4cb98a8..e997a08 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -5,6 +5,9 @@ signal inspected @export var dialog_resource: DialogueResource @export var dialog_start: String = "start" +# Should this go into a singleton? +const dialogBox = preload("res://assets/dialogue_boxes/balloon.tscn") + var opened:bool = false @onready var sprite = $Sprite2D @@ -27,7 +30,9 @@ func _on_interaction(player:Player) -> void: return opened = true - DialogueManager.show_example_dialogue_balloon(load("res://src/dialogue/main.dialogue"),"start") + var balloon: Node = dialogBox.instantiate() + get_tree().current_scene.add_child(balloon) + balloon.start(dialog_resource,dialog_start) $Sprite2D.frame = 1 diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..b79f880 --- /dev/null +++ b/todo.md @@ -0,0 +1,17 @@ +# inventory +## inventory datatype: +- manages an Items Id, icon, description(s), and if the player has it or not? (should they manage that too?) +## inventory screen: +- lets you see all the items you currently have with descriptions of them, pressing action button lets you equip it. +## items in game: +- npcs can check your equipped item and special cutscenes can happen + +## format ideas: +### items are all scenes: +- no +### Items are all resources: +- give resources through their url +- would let us manage multiple instances of an item +- maybe the db could act as a master reference, the resource could act as instances? +### item db +- items are all in a big list, give them though id From efb8dcade8aedd4bc810601513c724cb691d35e0 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Mon, 15 Apr 2024 19:08:23 -0400 Subject: [PATCH 31/86] item system2 --- src/items/item_db.gd | 6 ++++-- src/player/player.gd | 3 +++ todo.md | 8 ++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/items/item_db.gd b/src/items/item_db.gd index 4af0963..397c12f 100644 --- a/src/items/item_db.gd +++ b/src/items/item_db.gd @@ -8,13 +8,15 @@ const ITEMS = { "id_name":"test_item", "title": "Test Item", "icon":"x.png", - "description":"You shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden." + "description":"You shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden.", + "unique":true, }, 1:{ "name":"test_item1", "title": "Another Test Item", "icon":"x.png", - "description":"You (also) shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden." + "description":"You (also) shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden.", + "unique":true, } } diff --git a/src/player/player.gd b/src/player/player.gd index d3e5105..a412ba7 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -10,6 +10,8 @@ signal moved(dir) const TILE_SIZE := 16 var is_actionable:= true +var inventory := [] + var has_boots := false func _init() -> void: @@ -69,6 +71,7 @@ func _interact() -> void: if interact_tile.is_in_group('interact'): interact_tile._on_interaction(self) + func give_boots(): var boots = boots_packed_scene.instantiate() add_child(boots) diff --git a/todo.md b/todo.md index b79f880..31e904b 100644 --- a/todo.md +++ b/todo.md @@ -15,3 +15,11 @@ - maybe the db could act as a master reference, the resource could act as instances? ### item db - items are all in a big list, give them though id + + +# todo: +- clean up commit tree +- get player (or inventory) ref inside of the item_db class (pull from top down ig) +- add values to player inventory array (should it be a dict?) +- render items to the game when the menu loads +- update currently equipped one \ No newline at end of file From 66b8552a600f08912a92c04903984c476c63ad71 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Mon, 15 Apr 2024 19:33:41 -0400 Subject: [PATCH 32/86] I think i fixed main --- DevTextFiles/CODER_NOTES.txt | 22 --- DevTextFiles/Todo_Tigran.txt | 1 - TEST.md | 5 - docs/contributing.md | 2 +- .../ShowcaseExperience.txt | 58 ------ src/resources/gitnoremove.md | 0 src/special_scenes/game_handler.tscn | 68 ------- src/special_scripts/inside_maze.gd | 178 ------------------ src/special_scripts/outside_maze.gd | 47 ----- src/static_scripts/gitnoremove.md | 0 src/testing/from_old_projects/super_menu.gd | 42 ----- src/testing/test_space.gd | 117 ------------ src/testing/test_space.tscn | 6 - 13 files changed, 1 insertion(+), 545 deletions(-) delete mode 100644 DevTextFiles/CODER_NOTES.txt delete mode 100644 DevTextFiles/Todo_Tigran.txt delete mode 100644 TEST.md delete mode 100644 docs/file_exparimentation/ShowcaseExperience.txt delete mode 100644 src/resources/gitnoremove.md delete mode 100644 src/special_scenes/game_handler.tscn delete mode 100644 src/special_scripts/inside_maze.gd delete mode 100644 src/special_scripts/outside_maze.gd delete mode 100644 src/static_scripts/gitnoremove.md delete mode 100644 src/testing/from_old_projects/super_menu.gd delete mode 100644 src/testing/test_space.gd delete mode 100644 src/testing/test_space.tscn diff --git a/DevTextFiles/CODER_NOTES.txt b/DevTextFiles/CODER_NOTES.txt deleted file mode 100644 index 6342406..0000000 --- a/DevTextFiles/CODER_NOTES.txt +++ /dev/null @@ -1,22 +0,0 @@ - -ROADMAP: - Make the Maze a playable single player experience - Make the Maze look pretty - Make the Maze have cool thematic things - Make the level editing work - Make the multiplayer work - -Next: (Crtl+Shift+F "###" to find things that need to be worked on) - Look at Godot top down shooter tutorial to see how walls are done - Rework customization settings from Fragile bounds - Grab my file reading code. MAKE SURE I CLOSE MY FILES!! FOR SAFETY!! In TestSpace: - I need to have a way to throw errors somehow like what if someone makes there be 26 rooms - maybe a tile can have multiple things, like a transfer function and something that looks like an exit - Figure out Transfer functions - Make the Maze movement read: - Rooms - To make walls and circuits work - Circuits - Ok my file legend should also have "Observers" that the can activate circuits - Add basic art - Add some juicy sounds - diff --git a/DevTextFiles/Todo_Tigran.txt b/DevTextFiles/Todo_Tigran.txt deleted file mode 100644 index 37ef05a..0000000 --- a/DevTextFiles/Todo_Tigran.txt +++ /dev/null @@ -1 +0,0 @@ -Make the game playable diff --git a/TEST.md b/TEST.md deleted file mode 100644 index 2e79da4..0000000 --- a/TEST.md +++ /dev/null @@ -1,5 +0,0 @@ -I don't know what this file is - -hello there - -We honor the hero Surya who saved Brampton. diff --git a/docs/contributing.md b/docs/contributing.md index 71602b4..fff40d6 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -6,7 +6,7 @@ - Keep file and folder names in `snake_case` (godot 4 standard) ## code -- Make sure your godot code follows the [GDQuest Style Guide](https://gdquest.gitbook.io/gdquests-guidelines/godot-gdscript-guidelines) +- Make sure your godot code follows the [GDQuest Style Guide](https://gdquest.gitbook.io/gdquests-guidelines/godot-gdscript-guidelines), use the [gdscript-toolkit-linter](https://github.com/Scony/godot-gdscript-toolkit) to automatically format your code. - Use [Static Typing](https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/static_typing.html) for variables and functions. - put scenes and their scripts in the same directory - Name scenes after the root node. diff --git a/docs/file_exparimentation/ShowcaseExperience.txt b/docs/file_exparimentation/ShowcaseExperience.txt deleted file mode 100644 index 22aa2af..0000000 --- a/docs/file_exparimentation/ShowcaseExperience.txt +++ /dev/null @@ -1,58 +0,0 @@ - - -Legend: - General row reading format: - For storing data, they will begin with ">>" and then the code. Next rows will be "," or "]," seperated lists of elements - "%" means this is information in a line that will have the entire next line stored to a variable - Maze Bound: - R(id_number) - Room of id_number - Tile Bound: - W - Wall - C(id_number) - Circuit of id_number - S(of_what) - Sprite of of_what - Circuit Bound: - M((R(id_number)),(which_tile)) - Move to different id_number room at which_tile position - V(id_number) - Visual of id_number that plays until finished - ????###If, and, or statements? - ????Radnom function? - E - exit experience - Visual Bound: - T(what_text) - Text to be displayed - #Empty Room: - ],],],], - ],],],], - ],],],], - ],],],], - ],],],], - -%Experience Start -M(R1,[3,5]) -%Experience Name -Showcase Experience - ->>>Circuit Library ->>C1 -V1],M(R2,[3,5]) ->>C2 -V2],E - ->>>Visual Library ->>V1 -T("Remember you can") ->>V2 -T("You are in control") - - ->>>Room Library ->>R1 -],],],], -],],],], -],],W],], -],],],], -],],],], ->>R2 -],],C2],], -],],],], -W],W],W],W],S(W) -],],],], -],],],], diff --git a/src/resources/gitnoremove.md b/src/resources/gitnoremove.md deleted file mode 100644 index e69de29..0000000 diff --git a/src/special_scenes/game_handler.tscn b/src/special_scenes/game_handler.tscn deleted file mode 100644 index b0dad5a..0000000 --- a/src/special_scenes/game_handler.tscn +++ /dev/null @@ -1,68 +0,0 @@ -[gd_scene load_steps=8 format=3 uid="uid://detywurbm46yn"] - -[ext_resource type="Script" path="res://src/special_scripts/outside_maze.gd" id="1_538b0"] -[ext_resource type="Texture2D" uid="uid://d316msy0elqvi" path="res://assets/maze_assets_very_temp/OutsideCharacter.png" id="2_p76kx"] -[ext_resource type="Texture2D" uid="uid://d302b6tly3nlg" path="res://assets/maze_assets_very_temp/Apparatus.png" id="3_ish85"] -[ext_resource type="Script" path="res://src/special_scripts/inside_maze.gd" id="4_qdoyt"] -[ext_resource type="Texture2D" uid="uid://df17dmyxpjmrb" path="res://assets/maze_assets_very_temp/MazeCharacter.png" id="5_u6123"] - -[sub_resource type="RectangleShape2D" id="RectangleShape2D_bs24g"] - -[sub_resource type="RectangleShape2D" id="RectangleShape2D_5bthu"] - -[node name="GameHandler" type="Node2D"] - -[node name="OutsideMaze" type="Node2D" parent="."] -visible = false -script = ExtResource("1_538b0") - -[node name="ColorRect" type="ColorRect" parent="OutsideMaze"] -offset_right = 1156.0 -offset_bottom = 650.0 -color = Color(0.411765, 0.411765, 0.411765, 1) - -[node name="OutsideCharacter" type="CharacterBody2D" parent="OutsideMaze"] -position = Vector2(662, 157) - -[node name="Sprite2D" type="Sprite2D" parent="OutsideMaze/OutsideCharacter"] -scale = Vector2(2, 2) -texture = ExtResource("2_p76kx") - -[node name="CollisionShape2D" type="CollisionShape2D" parent="OutsideMaze/OutsideCharacter"] -shape = SubResource("RectangleShape2D_bs24g") - -[node name="RoomWalls" type="Node2D" parent="OutsideMaze"] - -[node name="Apparatus" type="Area2D" parent="OutsideMaze"] -position = Vector2(475, 288) - -[node name="CollisionShape2D" type="CollisionShape2D" parent="OutsideMaze/Apparatus"] -shape = SubResource("RectangleShape2D_5bthu") - -[node name="Sprite2D" type="Sprite2D" parent="OutsideMaze/Apparatus"] -position = Vector2(-13, 1) -scale = Vector2(2, 2) -texture = ExtResource("3_ish85") - -[node name="InsideMaze" type="Node2D" parent="."] -script = ExtResource("4_qdoyt") - -[node name="ColorRect" type="ColorRect" parent="InsideMaze"] -offset_right = 1147.0 -offset_bottom = 646.0 -color = Color(0, 0, 0, 1) - -[node name="Grid" type="Node2D" parent="InsideMaze"] -position = Vector2(450, 235) - -[node name="MazeCharacter" type="Node2D" parent="InsideMaze/Grid"] - -[node name="Sprite2D" type="Sprite2D" parent="InsideMaze/Grid/MazeCharacter"] -scale = Vector2(2, 2) -texture = ExtResource("5_u6123") - -[node name="WallCollection" type="Node2D" parent="InsideMaze/Grid"] - -[node name="Wall" type="Sprite2D" parent="InsideMaze/Grid/WallCollection"] - -[node name="Exit" type="Node2D" parent="InsideMaze/Grid"] diff --git a/src/special_scripts/inside_maze.gd b/src/special_scripts/inside_maze.gd deleted file mode 100644 index 14a97cf..0000000 --- a/src/special_scripts/inside_maze.gd +++ /dev/null @@ -1,178 +0,0 @@ -extends Node2D - - -@onready var player = $Grid/MazeCharacter -#it is slighty awful I didn't onready the important labels but HEY - - -var is_turn_timer_active: bool = false #I probably should have not had any "is" in my bools -var turn_timer_countdown: float = 8 - -var out_of_screen_position: Vector2 = Vector2(-42,-42) - -var distance_between_tile_centers: int = 50 -var grid_tile_width: int = 5 -var grid_tile_height: int = 5 -var center_of_top_left_tile_position: Vector2 -var center_of_bottom_right_tile_position: Vector2 - - - -var direction_dict = { - "up" : Vector2(0,-1), - "down" : Vector2(0,1), - "left" : Vector2(-1,0), - "right" : Vector2(1,0) -} - - - -var room_dictionary: Dictionary = { - -} - -func _ready() -> void: - do_grid_adjustments() - - -func refresh_the_board(): - player.position = Vector2(60,60) - if is_turn_timer_active: - $TurnTimer.start() - - -func do_grid_adjustments(): - distance_between_tile_centers = distance_between_tile_centers * $Grid.scale.y - center_of_top_left_tile_position = $Grid.global_position ##I need to move this just a bit I think - center_of_bottom_right_tile_position.x = center_of_top_left_tile_position.x + (grid_tile_width - 1) \ - * distance_between_tile_centers - center_of_bottom_right_tile_position.y = center_of_top_left_tile_position.y + (grid_tile_height- 1) \ - * distance_between_tile_centers - print(center_of_bottom_right_tile_position) - -func _physics_process(delta: float) -> void: - check_inputs() - - -func check_inputs() -> void: - if Input.is_action_just_pressed("ui_down"): - attempt_move(direction_dict["down"]) - if Input.is_action_just_pressed("ui_up"): - attempt_move(direction_dict["up"]) - if Input.is_action_just_pressed("ui_right"): - attempt_move(direction_dict["right"]) - if Input.is_action_just_pressed("ui_left"): - attempt_move(direction_dict["left"]) - - - - -##Add fail conditions and whatever - -func attempt_move(move_direction: Vector2): ## - ##Add stuff about communicating what's happening - ##Check if tile is occupied or something - var attempted_move_position = player.global_position + (move_direction * distance_between_tile_centers) - #add_text_to_step_log("Attempt to go " + str(direction_dict.find_key(move_direction))) - if is_position_in_grid(attempted_move_position): - player.global_position = attempted_move_position - #add_text_to_step_log("You went " + str(direction_dict.find_key(move_direction)) + "!") - end_turn() - else: - #Double check for secrets - flash_the_grid() - #add_text_to_step_log("Too far from center") - -func is_position_in_grid(given_position: Vector2) -> bool: ## - if given_position.x > center_of_bottom_right_tile_position.x: - return false - if given_position.x < center_of_top_left_tile_position.x: - return false - if given_position.y > center_of_bottom_right_tile_position.y: - return false - if given_position.y < center_of_top_left_tile_position.y: - return false - return true - - -func this_invalid_move_was_made(in_which_direction: Vector2): #yes this could/should be a signal - flash_the_grid() - var invalid_direction: Vector2 - invalid_direction = in_which_direction - if direction_dict["up"]: #I like match more but I keep getting errors - pass - if direction_dict["down"]: - pass - if direction_dict["left"]: - pass - if direction_dict["right"]: - pass - -func flash_the_grid(): -# var current_tween = create_tween() -# current_tween.tween_property($Grid, "position", $Grid.global_position + Vector2(3,0), 0.04) -# current_tween.tween_property($Grid, "position", $Grid.global_position - Vector2(3,0), 0.04) - pass - - -func end_turn(): - pass - - - - -func kill_player(): - refresh_the_board() - - -func get_random_outer_tile_direction() -> Vector2: - var enemy_travel_direction: Vector2 - var counter: int - var random_int = randi_range(0,3) ##There MUST be a better way to randomly get something from a dict but whatever - for direction_name in direction_dict: - if counter == random_int: - enemy_travel_direction = direction_dict[direction_name] - counter += 1 - return enemy_travel_direction - -func get_random_outer_tile_position() -> Vector2: - var which_outer_tile_position: Vector2 - var test_direction = get_random_outer_tile_direction() - which_outer_tile_position = get_outer_tile_position_on_opposing_edge(test_direction) - return which_outer_tile_position - -func get_outer_tile_position_on_opposing_edge(given_direction: Vector2) -> Vector2: - var tile_number:int = randi_range(1,grid_tile_width) - var which_outer_tile_position: Vector2 - if given_direction == direction_dict["up"] or given_direction == direction_dict["down"]: - which_outer_tile_position.x = center_of_top_left_tile_position.x + ((tile_number - 1) * distance_between_tile_centers) - if given_direction == direction_dict["up"]: #Below might need to be grid_tile_height - which_outer_tile_position.y = center_of_top_left_tile_position.y + ((grid_tile_width -1 ) * distance_between_tile_centers) - if given_direction == direction_dict["down"]: - which_outer_tile_position.y = center_of_top_left_tile_position.y - else: - which_outer_tile_position.y = center_of_top_left_tile_position.y + ((tile_number - 1) * distance_between_tile_centers) - if given_direction == direction_dict["left"]: - which_outer_tile_position.x = center_of_top_left_tile_position.x + ((grid_tile_height -1 ) * distance_between_tile_centers) - if given_direction == direction_dict["right"]: - which_outer_tile_position.x = center_of_top_left_tile_position.x - return which_outer_tile_position - - - - - -#Ok so like I'm thinking of a step by step system where each step that's attempted -#Is slowly revealed which I have the tech for but whatever that's too slow - -#Questions! -#func clear_step_log(): -# for written_label_step in step_log.get_children(): -# written_label_step.queue_free() -# -#func add_text_to_step_log(given_text: String): -# #oooh I can add colors or effects with RichText -# var new_label = Label.new() -# step_log.add_child(new_label) -# new_label.text = given_text - diff --git a/src/special_scripts/outside_maze.gd b/src/special_scripts/outside_maze.gd deleted file mode 100644 index 6d5a8e1..0000000 --- a/src/special_scripts/outside_maze.gd +++ /dev/null @@ -1,47 +0,0 @@ -extends Node2D - -var current_player_input_scheme: InputScheme = InputScheme.MOUSE_KEYBOARD ###THis can be compartimentalized -enum InputScheme { - MOUSE_KEYBOARD, - CONTROLLER -} -var movement_vector: Vector2 -var outside_character_speed: int = 200 - - -# Called when the node enters the scene tree for the first time. -func _ready() -> void: - pass # Replace with function body. - - -func _physics_process(delta: float) -> void: - check_for_new_player_inputs_to_move() - move_outside_character_by_movement_vector(movement_vector) - -func check_for_new_player_inputs_to_move(): - movement_vector = Vector2.ZERO -# if current_player_input_scheme == InputScheme.CONTROLLER: -# movement_vector = Vector2( -# Input.get_action_strength("controller_move_right") - Input.get_action_strength("controller_move_left"), -# Input.get_action_strength("controller_move_down") - Input.get_action_strength("controller_move_up") -# ).limit_length(1.0) -# var forced_aiming_vector = Vector2( -# Input.get_action_strength("controller_aim_right") - Input.get_action_strength("controller_aim_left"), -# Input.get_action_strength("controller_aim_down") - Input.get_action_strength("controller_aim_up") -# ).limit_length(1.0) - if current_player_input_scheme == InputScheme.MOUSE_KEYBOARD:#8d movement is possible... - #movement_vector = Input.get_vector() - if Input.is_action_pressed("ui_right"): - movement_vector.x = 1.0 - if Input.is_action_pressed("ui_left"): - movement_vector.x = -1.0 - if Input.is_action_pressed("ui_down"): - movement_vector.y = 1.0 - if Input.is_action_pressed("ui_up"): - movement_vector.y = -1.0 - movement_vector = movement_vector.normalized() - pass - -func move_outside_character_by_movement_vector(given_movement_vector: Vector2): - $OutsideCharacter.velocity = given_movement_vector * outside_character_speed - $OutsideCharacter.move_and_slide() diff --git a/src/static_scripts/gitnoremove.md b/src/static_scripts/gitnoremove.md deleted file mode 100644 index e69de29..0000000 diff --git a/src/testing/from_old_projects/super_menu.gd b/src/testing/from_old_projects/super_menu.gd deleted file mode 100644 index 20a0f9a..0000000 --- a/src/testing/from_old_projects/super_menu.gd +++ /dev/null @@ -1,42 +0,0 @@ -extends Node -class_name SuperMenu - -var current_ordered_button_position_array_index: int = 0: set = set_current_ordered_button_position_array_index -var ordered_button_position_array: Array[Vector2] -@onready var player = $"2DObjects/PlayerSprite" -@onready var tether = $"2DObjects/TetherPoint" - -var has_menu_been_set_up: bool = false - -func _ready() -> void: - pass - -func set_up_cursor_selection(): #This can't be at _ready() because UI doesn't set up yet - for node in $Control/MarginContainer/VSplitContainer.get_children(): - if node is Button: - ordered_button_position_array.append(node.global_position) - -func _physics_process(delta: float) -> void: - if !has_menu_been_set_up: - if Input.is_anything_pressed(): - set_up_cursor_selection() - has_menu_been_set_up = true - if Input.is_action_just_pressed("ui_down"): - if current_ordered_button_position_array_index == ordered_button_position_array.size() - 1: - current_ordered_button_position_array_index = 0 - else: - current_ordered_button_position_array_index += 1 - if Input.is_action_just_pressed("ui_up"): - if current_ordered_button_position_array_index == 0: - current_ordered_button_position_array_index = ordered_button_position_array.size() - 1 - else: - current_ordered_button_position_array_index -= 1 - if Input.is_action_just_pressed("ui_accept"): - for node in $Control/MarginContainer/VSplitContainer.get_children(): - if node is Button: - if node.global_position == ordered_button_position_array[current_ordered_button_position_array_index]: - node.emit_signal("pressed") #YYYYYYESSSS THIS WORKS - -func set_current_ordered_button_position_array_index(new_index: int): - current_ordered_button_position_array_index = new_index - tether.global_position.y = ordered_button_position_array[new_index].y diff --git a/src/testing/test_space.gd b/src/testing/test_space.gd deleted file mode 100644 index a686023..0000000 --- a/src/testing/test_space.gd +++ /dev/null @@ -1,117 +0,0 @@ -extends Node2D - - -# Called when the node enters the scene tree for the first time. -enum TextFileLineLookingFor { - CODES, - ROOMROW, - CIRCUITROW - } -var current_TextFileLineLookingFor: TextFileLineLookingFor = TextFileLineLookingFor.CODES - - -var room_dictionary: Dictionary = { - -} -var circuit_dictionary: Dictionary = { - -} -var file_writing_legend: Dictionary = { - "room_code" : ">>R", - "circuit_code" : ">>C" -} - -var first_letter_of_in_game_element_dictionary: Array = ["W", "C"] ###Hahaha not dicitonaries at the moment -var first_letter_of_in_game_effect_dictionary: Array = ["V", "E", "M"] - -func _ready() -> void: - read_experience_text_file("res://FileExperimentation/ShowcaseExperience.txt") - #Verify and raise errors - #transmit info - - -func read_experience_text_file(given_experience_text_file_path: String): - var file = FileAccess.open(given_experience_text_file_path, FileAccess.READ) - var current_callable_that_edits_stored_data: Callable ###Maybe I can use a callable instead of stored dictionary values? - var current_dictionary_key: String - var current_dictionary_contents: Array - var amount_of_lines_to_read_and_store: int = 0 - var content = file.get_as_text().split("\n") - file.close() - var total_lines_in_file: int = content.size() - var current_line: int = 1 - var line_read: bool = false - while current_line < total_lines_in_file: - var line: String = content[current_line - 1] - line_read = false - #print(line) - if current_TextFileLineLookingFor == TextFileLineLookingFor.CODES and !line_read: - if line.begins_with(file_writing_legend["room_code"]): - ###next5 lines should be roomrow codes - var what_room_code: String = line.substr(2,-1) - room_dictionary[what_room_code] = [] - current_dictionary_key = what_room_code - current_TextFileLineLookingFor = TextFileLineLookingFor.ROOMROW - amount_of_lines_to_read_and_store = 5 - line_read = true - pass - elif line.begins_with(file_writing_legend["circuit_code"]): - ###Next line should contain information on the circuit - var what_circuit_code: String = line.substr(2,-1) - circuit_dictionary[what_circuit_code] = [] - current_dictionary_key = what_circuit_code - current_TextFileLineLookingFor = TextFileLineLookingFor.CIRCUITROW - amount_of_lines_to_read_and_store = 1 - line_read = true - pass - else: - line_read = true - if current_TextFileLineLookingFor == TextFileLineLookingFor.ROOMROW and !line_read: - ####Read the roomrow and reduce the next lines until it's 0 and then go to CODES - var every_tile_in_row = line.split("],") - for tile in every_tile_in_row: - room_dictionary[current_dictionary_key].append(tile) - amount_of_lines_to_read_and_store -= 1 - if amount_of_lines_to_read_and_store == 0: - current_TextFileLineLookingFor = TextFileLineLookingFor.CODES - print(room_dictionary[current_dictionary_key]) - line_read = true - pass - if current_TextFileLineLookingFor == TextFileLineLookingFor.CIRCUITROW and !line_read: - ####Read the roomrow and reduce the next lines until it's 0 and then go to CODES - var every_effect_in_order = line.split("],") - for effect in every_effect_in_order: - circuit_dictionary[current_dictionary_key].append(effect) - amount_of_lines_to_read_and_store -= 1 - if amount_of_lines_to_read_and_store == 0: - current_TextFileLineLookingFor = TextFileLineLookingFor.CODES - print(circuit_dictionary[current_dictionary_key]) - line_read = true - pass - - if line_read: - current_line += 1 - -func are_dictionaries_valid() -> bool : - return true - -func verify_circuit_dictionary() -> bool : - for circuit in circuit_dictionary: - for effect in circuit: - var effect_first_letter = effect.substr(0,1) - if effect_first_letter not in first_letter_of_in_game_effect_dictionary: - return false - return true - - -func verify_room_dictionary() -> bool : - for room in room_dictionary: - var amount_of_rooms = 0 - - for tile in room: - var element_first_letter = tile.substr(0,1) - if element_first_letter not in first_letter_of_in_game_element_dictionary: - return false - if element_first_letter not in first_letter_of_in_game_effect_dictionary: - return false - return true diff --git a/src/testing/test_space.tscn b/src/testing/test_space.tscn deleted file mode 100644 index 18585f5..0000000 --- a/src/testing/test_space.tscn +++ /dev/null @@ -1,6 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://brvpbsqn7pngj"] - -[ext_resource type="Script" path="res://src/testing/test_space.gd" id="1_jqet7"] - -[node name="TestSpace" type="Node2D"] -script = ExtResource("1_jqet7") From 4dac484371499440576c7f02b440b331a80fe0fc Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 16 Mar 2024 15:28:40 -0400 Subject: [PATCH 33/86] tilemap data structure set up, make as seperate scene --- assets/monochrome-transparent_packed.png | Bin 0 -> 17497 bytes .../monochrome-transparent_packed.png.import | 34 + project.godot | 43 +- src/main/main.tscn | 3264 +++++++++++++++++ src/player/player.gd | 19 + src/player/player.tscn | 24 + src/scene-tiles/chest/chest.gd | 14 + src/scene-tiles/chest/chest.tscn | 21 + 8 files changed, 3384 insertions(+), 35 deletions(-) create mode 100644 assets/monochrome-transparent_packed.png create mode 100644 assets/monochrome-transparent_packed.png.import create mode 100644 src/main/main.tscn create mode 100644 src/player/player.gd create mode 100644 src/player/player.tscn create mode 100644 src/scene-tiles/chest/chest.gd create mode 100644 src/scene-tiles/chest/chest.tscn diff --git a/assets/monochrome-transparent_packed.png b/assets/monochrome-transparent_packed.png new file mode 100644 index 0000000000000000000000000000000000000000..4a99afc0a4b1737b34cb95c40736e1c9df11b3db GIT binary patch literal 17497 zcmV)mK%T#eP)<h;3K|Lk000e1NJLTq00R&J00CeD0{{R35sD2~00004XF*Lt006O% z3;baP00006P)t-s0002_`up2X(=z}700DGTPE!Ct=GbNc03ZNKL_t(|+TFbma8p;B zCwlIcEXlGg31e(wge8oFjWM<W$5ueGF5rMe2q?r5$AB#o8r;EPCH!-YvGgdG;-#o8 z%QC%8iY4COOqOL>#?{60QcRYpXf{RVQLKw%SQpC>70>JE;rV&AjMuGp)bf76b95~m zFg=~^bZxCpBomPD?|$d|&iDVE%h*$|rcu1{NiSLa-57s~Kd~S4lGt)B3mKfu$(W)v zjq1mme)#?e4nU*z%Cb*?a}Y0lHzesJny}_Ny~COt{4+VE5I(I2tAQ2M;4e!wqlf<? zO)&)wOcOFJo~HF*Z)~@-#<u*n6vXCDVSG)4k8gfwiRvTzNBTZKB1L`XfF){)ngdcO zqsJ1p(TkO^5`6^Uwi?7w=9Ei6(sa-Isw8KD)p=~)M~nX7b-_eXh48yRxc}+np~roH zhwpZ!8LR}+uR=It>PYLF)$54a-F7#tX4SY6=5)l8RJa%m%(^`5D$`~aGwr&MipItv z@|nE*%7+hb_YL(u{(tb@fBR<{J!xGuzR(tGOSDdHVSbx{$mp@V9kKj2kB41jzdSf( ziJDxqdi4<ler?)`3^psYIYgYWYORg!tz(S@;f)i76%dT2ChA}R$Mln8qIBDJej3}o zaWOJ_yz%O<^V@X(>_^#;4-R2Wzgb%0=Inm({ygSp9>%mQbhf6^^<zyWKYkrS<S<zZ zefZ$c!H*6e+$$h5dN{jp5XAPyYvr2i4yP8w?sl1Gx5-LgechJ2Edbb8HvQ)O)0_&{ z>(_1l>ea7_E4l&$3GA<%e*NoTuYZ!H;@SuI|LoxYgMklSCY$YF{gb?U;%FYzVz}+L z?4mwFg(LRTjbOqY$ZzYY?x@~Zc5rC_rRg_I>NterGy7*>ef4XtVUgDFR3T_(Bq3CZ z5)dAbH|~kPI^0Ra5|xJM9G!N2(TOFurr#{+V=SL!@o@EP)ol;=mF>TjU0hOUiE=W` z&32lnwIx|6mF)z<CyGPRM48yKPj53jV}DsSSX$bZR^3t5H*d#^2#x5Rqn&*&)1niL zPPk0dj?dZWjoaN?=jwuY3KY5RVK8B{(L{A|!CA+oUg>@_Ekd@cvAr<}b~m;ssTfJJ zdnF+L)jz3hDe5bl*D%yzZqOC=t=Lo9GV{zUX93|dF}8FI4g1n+MONhHM;x)z3ca6x zcOGLa7WQuKb<$Fi<#ive3qokueUud1k!7Er<x=4?m6rb7KdUIM8mtO6^fg2pMyduI zXliUWtHJJ`{gvHqHB^*Vly<NV=HV|#jD!|cR2ba0%<$}9#)`978YV$t>FG9adH{&M zF4MYoU1>T$U8Z0~MMFh{(`9PtQz7hbOVnzp&8p1;#0vh(F3#vNeuZUja-U&VDJ(H- z?KT@tR2vispD3<CKDaN~T{XCF-8a9>X(kCR@HkgER}^ZUJDfVd!D=;_Tz2>Ln^uF% z<TBN;8n*d92B#u~Uq0$4E@-W33W=?i*!=_4AZNE6OtfNk<6E<;2FJ!ilFknZgVW>m z5QK+A7_3?+UE5`_;)`yg!p2`FS4NNCz@Am+>PRW`P?8rR=|?K_$uCC?Z+xa+>bh`V z3?_bzwFqG_t0wG-(a#AG;$NhYj{Pl7AzM;4=sY_%=IGOexy=yc`s8cz9~0~aSLV2g zCd}OWh&N6@U6werSx6zM0DyRKhJG0k7sHzJ5&a{R3u=kfA*uC=W=RuXyjIu?0bw<8 zWiI}Sb*K>K!_u$I$Hsn>G$!=Y`Ehg7|3MRV_WK_U*-SQCK?zBV)sSs>SCnd<cx#FE zi`SAdBYPo!8xoa-pf7h=q6E=v>MoD#g9I^_)Gc`VZ!>cbTLxa-+m&(8F`8lJHlr(} zC*xje#lEtNQoNx&^6ClV8oOqRYRDwnYzyv^Kyh*-_CylmvL$XAvjCz;<%Z4=q1F5~ zc=2Fa`l+;EW_IIubpG^{>8Hwv4?Ps4x<f!@C$gU$91KQvE~}xa&kYDo*b=QyIAR=P zpCe`&a}WfWpA-d>D9t7;J?F&-%ZwW|*Jt&D_VklP#hvnDDDUm_f{E%5lM9-*uCZ>z z!J(CdhX$>NUH3Ag#C5Gxg_zZAayv#H9O4~7^zWp>{QoE0>|}ojUOYTx%d_QK4Pt4{ zJTvpNnP&tyO|HroyE~tZ5<xB|h@ll_xdS`<$+Lm~V2K7hIYcbel{=a{mJ4ML5$@ly zV`smP{S7$s|A7||4|$e)qndDahbK;Nk7ubR+B$-<V@G96ep_{i-F>+FFqx#4Ln|-Y zY%P^~C+E6=uo`AX7rJOoj8Bx1bsbHV=?tGJlBnuHQGf10Wee0H**bCp%J%I!P_}Q^ zy~>u#mX2zVCs?q)pzYy`GC=(7OVYHCn9U|2$V~~CF_qoksJfhp-C;>#)4_{}hrInx zUG9L+UsPC8s*kMh&*(8&om$4;{FTmM+0ss0wB5eOuIM_*BspTcuUHknlJ${bha*Po zJ6y`j<K<%zTJLa5Xg?(-$>xI>_jc)aR7HeF#nSTY08urVe$uZq2P#{Hy;#dsleGIv zRz2qhqt!xoIAjUiS@|$Q{AMDA&L8GN1zvprLyo`dQBE_NrNP{R83SpNj2@FqAIa>7 zU#Rn|_ClDX?BdtHv?{7@vEq~D0uvR70`W#wUNH8zgdy(*FTxt#d)fkhg!?s4?osh| zmDZ&R>-^?`YA;q^$8f}!A2FOrE-!<st60i~9Eb4#Em_1gKwKOfn+O5RF;M}UT*6+s z$L+=PBYM*_nm3m&o=d|qkor5-UO3PGC}sZi>*1lXG3bM5?FHGyA7L*f{BkWz>tasm zL?^NK+{gd$=jT2?_c6a}Sg1*ESQpU0pH0RWVXae*E|{6TEju)~s?aAxXd>J*mrlY_ zXRN>~g+Bjnn0=nKdMX6}t$z+GlJP}E|2XYSL>IIo@(HAx+)op%HwKH2TOo)LIXR(4 zS(zagAR`pr_k|_;{SV)deV+`wRERSom?A3v&3}c6(n@-)f8>Z2_0g?Vvn{NXnV4z% z&FMF@ZcaBagA|35BuZf)qb!|On(Vy>g3!d=HICT#KYY$1COQI~ioKxXFaO41o&6Qr zic4u<zWVjT%QVFuY$;0+E%~&fh8Nr|*Ghe}*qoztj)GcCG(E!7Smg=p14AsB(8Ok! zSq-26_VcmN3E<EFJY_Eb?@$ur?7#naJidrfgw#)tXP^ENi%9_~PA=uV1$Rp;0HGN! zh%Gt+^-?uxaxDupowd4y-LexzRlLkDh0cBa{n$D32H`Q$*mGcyZV!hbi3%pJZZ-Ne z;kh^D8hI6dYOYIBHXy~=Dz<9t)rN+q(JiumI6pr3#=PzN$VZn9){F>~yYkz#;o0$z z&sD`&yIJ_*q3=BpN#%e412>+R_Fqc7L<j*klR1Nlum8iWUYl)JZ(f}(+h8ruw#rgO z3e$WaW5=3C>+>4hw;r+FmE()of{Oj?5WtetI&Zras*bleYGP!eLbN8Hfp|bt8PG5# znD`H`E_*=ng~x4u^|B*YKK$}|n#eAFMAAt*0kQn5BPx?E@y2rp+VTxn(tugD#C3ml z0#TCmm?^X-f|#h!f18@9zhztReYjUvFi|gGeCdm#zVeYmXVsuSQdp*EdJ3pztxhW@ zN?BUu&m$dI-BC5@jgu4F#W1%Tf3P#Nd;MqgZ?Le+?$3XlVz*e`WHZ>m|93pT=zHnQ zqM?^B2FykMW?B~MOly!0g5A#Hx#5BsVpp4O{Sy*zKP&M`CudoM9a6~AJNpz<)OEr0 z2g%o`mxk8;^*@tpooD~@Zz@~n-dJ+0D&o>s4HorPMNBk_CT3tZCWO{GJSXH}xQ!x; zpuBNVQI{TBM(c+l!ul?Wr65vN++H_y>97AX-RHdcZ~p7N?XVS9eN}znVbvom=~W7T z2n0)Sdad>5G$uubriJ4~@rCTuhZd2JB7+plh(dvU9)|*XcB0aJ&a;RwxaU_04=}Au zTi_%G<YImrssb@H)jMNs?hV8jim(@4qlB?8)RBS^X_lAjoEMYvh0|CE_Y(F(VHkjT zz8ZW^eDP3q?k1>nkt~`~_eZi9FNhM@WX<&lybRWD$9DGnb!6FV>zSACvp$b9AbBZG z%aUq0B!?t*I<PR4X|d!GzDxkDAZ<IzB-!1&ue6RdCm|3f*XL0N<Y@@v-Z!J){7x`Z zWhWdIl36XQV0M^tZ=BR=n5QpH;+Hh=K(<~L5VWKd^=v(-f-)daLzn~Xn<rgqxODD7 z?f|IQgegQZ)5VN**QSM+%ZHs>MJA&})`P4FvxMk7kqHpEPCaYl5EM*44MDlA?yL)c zfeF$&3kv}R!DWkCH_Kv$ESp=4;il1P#~ECy^Av}#Wh^~B0YXevJ)fxhyk{VmZXt-j z*a&A+AHkZKK`L<iO<EKIww)%*Pnv7EY+utTQFxQxlqf&N%=*YO7y?Yt&JnQNs!W97 zNyWtBYtl6iL3{)i^H1aNr{9#7+yTyVED9$+%l4I4ln*QNyzT5bJ1z~Zf3p4_*$WY3 zst}l{$q;g)vs3QmUwV9yQ&CuGunP4c;yrS*PBH{Kp@o-AD@y9NTrJzjY_d%g_3M0X z<nao2BYZWm=Rs&XRS4<E-Vms$8bl-ln*k7_lVK1D1G`J=wk|E(C%H5(P2|wSCi0i{ zE|%HNdGU+p=Tf1$#wUuTT+=0mL50gywr}o@qCP|uNKK3{3pQ^%*o}$Ogft<2sJ*d? z+ylcIw);vjp+d-pXCTJ4j^0!d0Tn_`&%IGKSlI%rz%zJs4_dCw1-r>ih0P=%4vHeJ z^$c1^<%N)_0EY-ngfK_wKVRURCx5ZAsIQ__L>FRx7`Ux~#VG2Vab5^5%#@uWUa>^8 zwlGRPUKJ2x>D99~4$(FdV$UG659r)oa#vbK=}TXT=)%gCgq7P0d`>%_J23rbQ6KQ_ z49QbVh^SC#qEvQ^rB_e)1PI$x6Sb7F2O;^J-?>b}^%tw$67_SL^^?>hS!8lS2wVi< zN@^X7F90!l>D6<H`iT(B{xdrel5dYCLXwt@mpPzyrgb@Dfb#Rp3wr^V8k)<M1Q0y@ z$0=iipx@Mo*iV*^V$1$Z2oOK|qKGb6KT>2_c^U$LL;t7%Vn35^iyYJB^bk4BI^u2) z(@`#nlJj$KJY&g(jsh=Ey^afue3XR;lj9Izw?B<1I&C&E+G;?N0Zb<?TfzzmqRj4g z8nE(3F+pUACRlPv)WbvDDP>z8M?UI5{R7xG4v}+!*$rF{Db_}8DgqhK+#IqDB_y-< zCAZ245Rq#_tUj19`m|1i)g0iE8`f-Cv-*i5V}gPS%14c<`KS~X0cH+o1OSoKjHrQE zZ+K3ME?!Sm<g>5HUYyT0ln-kaR_rr^N_eycp~y9-YO(-v>UA=w;|YpM5ERSl?Tp{` zjPtPBxVXqk(V{4%gu9dNBQ-dXOKzt=tap9*DR^eHl@HV82NSOs)E2CNQcDn--N;+0 z`6yE5iX@b|-N`g(7lpNylg%BF6`{sOk%|^YJ%v#Ui_AY=+MH`Bt<Wlln=7x=)KlW3 zY+rJsd`1BQm8j;Unqs(rc|2Jwg_nfVhzHYe&OAc}jC#Zwyf{Ucf)SL|Q$7rcg_rd) z%kawUT4zR&+YX0;y<UKc`uz~BU(eF~+KAikseYB)3pn_%el1b>#O+0B{%K<Oz{1Pg zn)HzmKTUJm-CmMRny3wH_(YwmmH)-xaftDJ6o(i$N$kKLruEBV^2hrt2MY`5y+?J7 z?Js>H6M(Q6;DvRdw89bhj{1z+E=MoaJ5f<{3KAtCplwt6C=Q{h>w>wrFwA|`#iEGI zM3-+tJXct#<!%)0#mg4~vEc698>>fyiA<NHm&y?pe4_a3CW$(k4k=3Iqn?7WyOX*T zx|R&m_Tp^hp9~xT_9Ay+!FlTd?)xy=AXB&FD{s6wn=@PWKpq|nn6WMZ@t^+T83=Pg zq+tfC`m&2%rm8-p4-i&b%CHtLHuFr;O`C1WExX%IJ|Vc^h!tm(%+;JySGUk7A|FLd z=IMz_`j?0;5Ct-=(TBhE)8(PcX>kTzHgkXz>%zZ415jvxGC5H~qEL29<)fa0NU9qF zflpK|U@wHVfW2@;g}s>gN;=n*mAN|Db5!OZ<wcApv*R5T&gLKGlC(ZeVwnnC!69sp zB*Z@co$3ye`XT7JH~D+3A90VC^diz&Wbl{rbuK2=qh6d7zxlqEZ6-_bHVN9|wSb_@ z|N8SWDFPwjg;lov2nCx_;hKIND(XWua?eQaKoQj=SsCR_&BWlf;F{#*ztBk>A+EAE zeq)>O7bP~|rutPPs}}l#R0m&rX%S9UR8T>zbPI^Lx*OZyxa0Ax|A^NwtgMvmg`K^} z%vwLKeizR^CRmKwEis8ihL#>h#|fKm^L_ZVuor-EBq6+UpBbwLk&g<o@}?zPQ$X%m zw0s!WkE~uTO~@veWpEi?S{wb@CJmwTTx!#wp@}^~5O!v>f+tzEuosvpKu7|DiR38R z<w5*EgtmNm^`o+Vtt0E7l<gxHmJ$U{c9F7vu4yiVi#5}DNFhx2?B0BvH$H8EE<Mvk z1p}MSKzgNn_Z6_)OAs`RnqXqn{oPk~U)gp{@5JSU2^}pdpRuN3;pG~#G3CRvzaj>E zxXq}cFs9PFouN&_L%=n5o2|_ofAs<JV%CYx_ieV#_Zh?G#vyvx7+sPeS}IL0i%URA zA*3DV-k5vi?eA&|Y6>#DMQp*kq|mNkwf-vj9+#`H*a>#j5t|>Y?pXFULCn0xA?{?= zPKJ;OLM8}IUq)0wAlyR1cH!lB9?$AUHAci1WHmzjIRv*KR!J)vuzV>ibsVYZK|WEo zry#<B*q4NG^df8#3Ssr5CAW&R-+7F@R9crzivolEI6hG_L6G&(%FGgTkjyQDMA`g; z-NA%k2MCqj5?yq!5uAYdE{TH%=3n+8V1Db9xi>ampsdsvlq#hQ8floBU^hh@p=_qr zQoIp!9A9vk3$4uzp|#mItP!hQRPECu5>@)NQBVe1njQluq!87k@^c3c4rLb?7E&5g zL3EK#gDeIYS_37(ih26L5i2ur-;fsFL%#IxD>7EVL<mQ06JHlp{fy_wAWu5hmjBVZ z!or_@nN>UEJegI+%0n0%sdTaQ$aaKklD_%O0aQ5w(F+B#`M$`~OqeLr_M1dE3PGr) z#M&&6M^+ZEwHmZe6nKOpM}(15AjKSlG9m;)_QE#)0xw*q6uU9Rx&SYP@1&1#Q^}Jv zM1ettP|!0pt_H0Wy!_|bi-{2IPyGV$So}xX3!5##tM!;DVG~3|Dqh*eu)`Ahu#2Xh zSakeEsuwDmJxIND<HIz`SPBSl91yJ|Hu_WR2&8DqEnGgk*kHvwEu0qC*33Ct;8dM{ z48*MyAW~7jR@7!S;bn+PNDbHyFyxUy#p+1wNYm(>8{XXT@j0-xq>j33tmRQnC@lmz z8;c=MRUyz4BdSyU(>Ojz6m)(R9l1_`ra8b$ImC_~ju@q+<u$)r^Q$GdkbtOcsqQdX z9X%3K4&RLZ)o&t5lcLC$*`3yPaEPd=rQs$8-bR)~9ZsI2Q9y-Q-Mt6GrCMCNrP6K3 zguS_e4Cpyjeo>aqE?#h%2oFntPgI0p=@47MOA44NZ$gP7a-w=^6wq+eyO5orGBqDF z&d-i<UK|K7JlZtcP|}>^)CwvTdC4tY%<cv+EWLbgU-_4>{7aU85_Vix>~1L(Of20( zTGh%TQn%EN8U`P=QVo@<&!AYn?19Tp6J_gN)w}ShA~&q@>%bF5eshB&gBPkySuPXd zRKZM#7p|ZOD!<Kbx4S#4+wzT0qf-iJ_%r<MC|`Ubc3h@)Ur<w6i0Fc36TBdZ%LMTW zAW(x}^Q)#&NR$9Tw+&ej4#9YiAg9?IU%JH`-#(8@=88$l2pPkMFxdzbe;c#`wRq`` z^NE^eQ|>RkEY?L)-|{2NkF<^mDumD?DAZ7`h5B{~BBN(kFA5B;BXf=df>d`XjirUO zA=$)7v1~9zR0x&bNeG3yh}`zASGQgTC7?nGZAl$8lqmH=$d_(GMrtROtJZx)C1{qx zSDTq?7+SpjTGzCjD#VQQLTGJD9ww@;!LM_~&_ngwFJJp5BuWTvbq7|0Ch5}7IRElR zB#RCXEjrOUa&TyNXm)5On--c8GT00TdXwFldmLSm80ymNRr0{*4FsWogodBPl&-_N z5JGErqyJA;ib$a@xkW{i!6mm^Dl1BDlx?*MixIH)(mOmoTx3-X4cuN}T_`dX$Xf)# zY$zaMqCP&S3N0<Yf!uKjWYUoP!#tpICZ#`ChF4&aK`QgB8IolWlJ)||NL7PstKlRa z`@k{|flJde3_lCeNu!<KZR1|^6!FD#)p-0Vo%++heuSYCYFFerQ=_9=jgzbfMV|P5 zJ~c3(zGtjNm=sBbSGfI??1dvLE<PE8>SN=fnAI@3ph8NooB5=G!el2YKeIZ>p$KVC zN=G%fSooRP4vL($sh1Z{z8dib6UioI#seupP-r5>r8Xz-7g?U<(8M%kSEQSoL1|!I zq98cpGC>3#EJewOpQ?eSUk3=tog3wUs%DaF-@@ADyUJ0yi^RvB94<|-+$-0x%bFfd zR9zR_6VzYppfX<vHAEs4CI)nEz|7llqox4z$GE)PzTg4qAS$ACJ9p(oetf#$wTY%J zIi!p71-XD7pwEc9x;J<77G_7Rqq?D_^9e2uh{krG@!$|RFw-{M-8$lk;qnU}<PLxi zkB25HR+gZ$Lwr#<kf7|U7=EJezO;euVU0{tbyQO)Rnsjo+*`w%&TnyPOvRR^K4UPE zJAj5DK&*d)%OkVAfHcm^>+=lrOihXM!NctZ&Ta8&;b~!s4~p;-#P)O4NES*#V4`S3 zcJ?=X(wPqkl?o^d^vhwQ6d9MNF6^G%0h5W84J9w?2Ad*>Z_kaaj%I`wgqDTo(vUo4 zE7nP!Qa-h6CMRkSwZD$DTU=VrNq~x+X2EVn#^o{A-LaeN^QwERd$)8E#FeV(`si$i zk;|%>&L+EMkIo}k%e>y2*`3*479uJvF~|`viwROGp*uf6<Gg@ZWOGm1-Lku_mFw=z z7^=^El^`6Erby@IT%t!T3M1)TnO8D&{8QYi6e<&WTdeN7hPnn^Ugbw)J0R3-w7I9e zqP)TqDX+*FuFcAKJKVFon!184r`zFkFbmOug#m>wsu`k*2oTO#Qh`wT(opvqE)Pls z%P~>-Hz*LgeAE&#Q6Q<0y>Uk$)kmi}-*S3mx^A1VBvcSuK)K**etBf35Nq)4D1ms< zpG3WXCvCR38aC!VMFq*wI7A=0sbtVB5q*rxd*o%zaL#ZR9+$h!J|Fv###`*|WEdb~ z4b|bK(&0&-)P=<m{75D>X>#}mfutHVSv7u$w#k~)Y)q=Z8A(gwe`@d&-yd!-3|95$ z!B{eX_rH?8i0FCBPpk_+(nn11SN}%+`}sE}(xRGD(z2dey+}){Lle;)OXiKoEu_oz z_rGBX6Gi$@K#0}^@dY0ZT6l3>UJOx!=HH@xBUSJs=qVxq`jk!NR2>z`Z&jIl<3t5o z*d{>ObOeym^ZvJc4me`l4cj44adCOd#Bd1QfF`^;rthaM9adIJqZ*%bi)D~~Kw$vW z45-RHtCmPGoKzu#aYrH;gLca3*?N`w%z1BwfKa1aK&*ZwE0jEKbBttm)2y|?df-!z z8hh9Vc8B$7dQ=^Sc!kZU#(x3PoS2m#q@5sDgErgNs|xiJ=xG2#Tt1^mK>X~>={Lz; zi+d^EyE?)nix@uT`xyfiTYM><moKE;W`bBshDJc_PRzO%q&)Y*p~8yyzg_o{4K<~> zfIv6`>a+&8eP=&1`T>udGUC*)ipV0$Kd)+Hw0)pPs%4FnAm*RO;+hB%Fgvxu1Ryfw zW)Ikn%R`}4D*%1>{cjIbW3iHd$bVo@Fs|`W_meF7HGb)dJWAH$Q+9@3Qzwc;EXY<N zS}x2wU2+CJ5D1ACdFC0@3G-PhF1uBGvHl6{MNuE}Z|?lg3)JUyrZSup&J9(D=Y^#s z(g)HWsakSN_DK*W*+P9#NqW<)3mfabG&R%{n}82uG64c@y-?=s?yS3GGS%myo7ocW z$cMKT+%YpWlT6aW(90pR6A6lliS0VKuorNf38FZgSK+brWC*RxWHrFjL04rCVxpW( z*o*Rtvb$*mfOz9hbw_74erHZ+Cc{|5Hp5PsOuRos$JHRE!xRotKCI?w=)Os47hha_ zar#Yk-csR;v)jpV`INmVsl%_XPXy~)M>f>u(2~d@gM<o(!7U0Vwxlvgsh1#-@S%_- zp*Hlqy!Pd_CRY=cYH00pp>?v!_9CwyUW+BZSEknLj%93FXc>Ezy81*FL)5=vD-d_n z_o56tid?))wRL1x0un{_#V`UHk$m6~lkCNc6+Ebny%Ik-#G-Fe{`4dE4z(4+PFRx) zUNl&0om_!HEeHs|4!l5+B}%)(UI1dUz3}kxL5kQJ^|Fi`q3zsGC`pJ(YVfDF7ZLqW zZeM=*emwA+IFjl*A|~qX@MM#O06Dn>18P4NUp)Jw%wo(jDXKuUhk@c1s@Vd<@nll( z8C{lo+pHp8L`+Pjh$aUWQF5dyqx0)uGjUOMK#~-h;#7uW6qJb~HzicosSxOk;^lN^ zwDKga7;2u*is_%>la9kSQvYG=$orLko#@*K1f0%ACj<nXO`^hs%ezc&J3w^)%x(bz z?;^v>x25o5FwDV39`(j(e_Ys8MNWGF03ZNKL_t(|o+-46qK8BL{1<**bI$Hf%{hKu zecn5dq3ANAfDlg4T87KJ?Wp{U&|V)w&oAhp%)d_^MDwQ>nruNk(fdhex7JGG+@1q1 z-vZ);D=CQ95$Z{0+*I+h9xhKij3U_Cq6s5Yh5tj^f*gb{sf+R9jqf5Av@+pE@YbHT zHvNXlrSX09JJwRUV@HaLrcYD|Y_(J&a6yqrqiU|bEuVIsxM!Y0{9!dnibj$6@W$Wy z)T>?Jtvju-ruG?Iraw+Usj+eh@M4^b67Zt@C?IB@5xh`%F%$NJV5yeekx1+E#znQ8 z)Llpy&I@HxzaJw_wLh?zI-)wmP3=z4^ayFG9)j3&0K5RR1w<32=lzw``yUl?2Ovaz zvF?t!$8N@E4w1QBbfR)_#)TQ|<xnP@!DcZBIU;RL=c255czFr!%}7Cj7p?c2bGSrZ z02RS2`Y0d-;}j+WnDUBschUw{Uf(%S3L#5HS*h*WC3$pl9W4qiWj@+SI|0Jxmt0Pd zgM<RQmf@}dK~&r$DvaO-rCY3wJ8?W$$WrlzCc5%^z-)3sSwfI=`(T1*QFM{VA+UUO z(1T8=+d}(eG~r3>A|+Af!;E`=DD3lzq76~yeZpQG9I6^b!z<q!IG7vXL?ylX>=0|1 zkk{rLa9#Qk39WN{U8oRZ>5&TI>H%&FAST)ibY7z=Q4CGoPh~wU3;)yEACf-oUm^w4 zI>LD|zPh16gauU9pu$SCQ}$wf=LH`uhGK|wQb*L}7pcKN)L#4uW&TsY+RrgHmPn=S zya^0-`v?}Fh}@u1P|zLkj3SMz+Q4AQ&w^oPlFAq3w@pb+G%<@KhMn(+kT`@cB9mD% zkvfDe!Jv|8)Xdio3{*7>A`(&jyyS}k6)CtC)-X{{AZD4ytp+#w*~qj}YzhclOiQd! zr@dtFe=AZ*R)hFSS;H=k;-#cxEo)Lh67uQ!ZE0OPzi4hEp|#n3#->r~t;|xTsx{G? z0EAzMk^=WdVuolikr4$IVlv@#i(&EUyUIgBDik+{+lU6_aF^VA3ZjlwUk&Y2Y0lYo z4-m~VAabJt8HEuJ(Pr%>i0;Z3SOaJ$rxrVjy|nlo=PkZMB^X*k5FJFrwqv`G?Y=_Z zZUWg}<QNgr8S6?487tg%Z_fct)CU(ZQ8_k)45k9&t<Ri;H3b>8dn%Y%bb|ILX+@mn zrJS?3&T+oL9}F*NP5w@Xv<&S-IH1TYuPdF@H6(vNipspvXUu1;4G^H>=Nmx9i~(h_ zh5{}?Z2Dk1We8!WP+X+_Nh$=jrg$%U>!zJ-jVPhFyMr8}l@@Y+-n*aG_t)p`%xn5B zwJrdnsH3`1h4|nCAZ8EvbvXk%4)N}1EB5$|8QqNS?B6~QgBJu!HkWLl_cCp{Pd~mo ztSE2#10<i+tz)Vh<o%QV?|!y3kErl?z>8&HzxqI^bMOKal}}NJ-fsy&fLA}NsSKFW z4yQuY6bO**^GdWc47wUkXmz+V+(PRC^$<$*!<2Qdyxu7j6&??G0p_({5$q<pA}VH) z3{?*5qF`@x&g<uhiYOqq9mDV$QA$~UWZSVB2BTFjlt^ebp|uPf95X3+5v&#|Wtu2x zS8RQ2t`u}M>sp`qd4Z8uFIS*H-?Z_P;6>{Qc(8cwl3Okl-Y%2Tn&y;-kp_@>=pvSu z5Lo;qp#?<KsJPdO6Gb}_X(PKiP&FupKKRAYzN{%Q`oZpL$6q;{(Uadc?Ra+aq7&#z zBUKz1-nedj>+K{6#CE7(078hZSQoStG4aY-^mIv~pKq!u2qq8<Y&&MKw&mj}2n35B zPg_1O0d+jRM_Jv^#}!CQ4NhL&{LqEtQV5$(@D1wP<S~dova?^fJeKI8hZMv-_mxtE zqo4oe%KYQTpB#c_h?1Q7_(N8$P~sEg3=ve(m#E1hz}32_h)c|6ed<bXSQgRshLM`6 z5bOaU6d8@|0yPy1kU?z&ghI`UowB$E+FZ+=;WkC0<f&6DsSq{n)PlPReMH&-bu=-^ zRin6=L!^Qj+73X2in$vo8GVZwFRz5ReO>t6wErk<i?mVirX$2VIK}G-tIKJ|-2)(_ z$K!eRYq8N(Krlh1fY?6ooyXXJ;WMt;KvZ0&SXA3Y{ir)fF>zEOrm(~wSaM$qdBapK z=3Qg7Oph4dPAxX7h}6U+h{ks5>colKKCeCxiV+ahi*k$Fo#aO9<P45Nh<El|7>k<S zh?JH^%mGc<Ll!TKxsPav(4(s1#kjPtj_SkLgc2c$ElUMN?!bWqyRW=)M?jzf7Hgih zZD)R>V(;i)YP84lq)zZQz1=cQ7muWoP48qoXd_8YjnQ2-IPJI!G2U`0a|kjOl$FUY z-m_;igd!K7&OiDd$<(_~_KpTW!$j@6r>Cv|D^K9;7*8|h5d1q5I}_^@HEvcnZ#y8w zMDfcnrBuHxCTi%7JBplLeBi*gV{hC+djlxIM3K5{+eRz830xXQaeCK1N}k#mT?b?H zDITpHOhPbrYTkDIEjA1$mH9-7_C{|!r+LpFlWWll+WSG?`PQp|m|wW?s6W&!AeLGU z({Jv&N0mFfJ5mnmuh4g`dQVK0J6uP}8f>X2lSCGM(nK}3&!+tz*dqvDfZd=#KzQRz z+WZPZM4J+pQ3(95dsM74*#ih9^>jMUs`osePEVFca$1Y0-!%FxQKuIEykIq0E`-*2 z=%Fh+t9H+xZO7UhQxgSo&S$Nq+jZU}O;48d9+&1ETE`}{d-E*{>f7w@mDgFRr_fX= zIa_EWdHP8eLI^AbmqWB}H<*h}!Nh?BCRcl-2mnM7V5LZ!)<upzD|o8b4G79W*_c*u zv*lAO2_;s?8*9SWVzKm|13~fW2iqbpiv2q~cVB65#L`pQZ8Z=TiTCEQQ^9ku^YGq} zI*vi3mB~)98mCsx$eCCjqYm?kNCLP_lN1Q`;B4PLRBXzs^>}t)S#$!tzyJidB8m4_ zIl%5%5`w$ahNpH_n3$>tg(Esi4gLv~`5*rJ!^-Q29ukT^(tZuRU^>(=SZA_cOggm2 z$TL&g!;{L?0%BrI0An510dq&SDD);b(IvZ&{`G%k*!=b}gG4b>BW+Ad2pdjajNuBC zVCUh)hBY;EO#w@Gv*;tD-et5F)bLj6a1C`x`;5Gak@Lb%8EV09O5C9i+?MakreZ?p z`-x7b8Nb`KE^{0AtJ^xLReU3fKy8+4_|s3$q)p#i)WBVikR!TfDXPn;V~RvJ*0_+Z zfBN4D!fn?)EH;tG?SHR27}AVS6!z{Qo2mU86SZ;lEn{sK`o~3HZT45`Crj!G!t+Yl z8$+oM>Ow%|4mh>6gB>|w?dQKG*FRuhvC5U**{MI)SskP;?j;w>=`EohgYJfU`a1;` zADTrbeQfN9?-yQPyO_#p2AqfDj(KC)G0AgK5mY*6^}hct?Z))@bsp-E;SlQr#U@H% zW4CflKfJNdm%Xu03QfPMH7vQMwW<(re+TpHjgO7}?i+JJRtjp2b%lj2;u-YZOeH6U zGGF~jjW5U>1d|L|;Du1xqEdt&+3aH3N{yh$GpQ<$iQ3Q(UH~Ey)JI-9YjVNslfsU8 z3PSa1u|sHi=kg<+N0JcDS&*nk_!;ehKr5R>H6__v)Hm&m%se+yQP<wMMz9+Y@N5Ny zCNw9WYI{#Xklzj}1cV~*`3UQxo)R(ndB~J!pNC&cOm%Xm9c3Ki?eD;DK>Y3-G>8_| zl=x_yCYxO+MJG-a>fE40#1{ksIgnR?ig)`v>vnzyh#AG0D9QweU;4r_qHnLEZ*3e6 ze5z9M!}oJ<fZeDFS2O$hOy5Ly!|J_Hc@@8BXFq2*q~z_eE1Q(~xz3W0M^WX@X-=bU z*hn@`zga%g8gg@9_&!Oki#bPCp{1gH+|)HuXi;|(IT&hnhtQhLCbKiA*wi}0{o8g> zG5sb%gpgc8_J7yq8n$s0mL6_LK%korNhdljgK4Nn@$AyW!1AM|w=J?QvS|cVynFlY z+w(s|Qpjeb6asI-H@Oa<PVequA6(ct3MHXJVDV8$u&<!T#5K~h3Iqd6gcQi`q1{9C zMvCd1t8dS}{njH(RBSbqlI%Ntp@?CkYUuKU-Tyc>sP=l28vHS;{0~&->?a0k9bxU) zFkIPtuI#;mA(UY8UA}1~gw|2@#kUtE?Zrfh=WQ=ZWv!^t^D(ah6`S^S`{ljgi6DTn zk~-d~J0U2bD1+N*)zm!S24d?O9lSD-s#j1r*?w*Plb!vvx@CPt<Ypn^3$is~bevLY zfx8BPfDW^=N!!Ph?Qzg){G1&UUylcM0=Uj1YK3yCw&j^Bi%l&R3+|P4Iz|_rfY{DI z4UshZNZR?HBt)=)m_rBUO@`n(GKTs*4!J_7Ax`Z}L68F3dTqm++8kGQbJp6*y3YDM zG^r|b@m+$TXh)F`f{LNmBo#%8*<U3g#$paVHQ2&&g?LtX=={|km?o#TY+rSUIsg&c zP+MzlrWQ;T_ox8fjcpPob^L5BYcP>>q2$8G<`3u-4It|i%N`_U9x6QvfvF;m?|+ph z2`(o(Jk^1NCbF{D7_tI6PU;EXd%Hd_tqXng3$oQNgZ*_I>q;*Dj6MOej^X?a0WmfP z2%TT_G1IP}h}VPtV@~bd8~n7N`zx<+zD^JaFKk$|>rS&7TYvXb?>{<ps4?TT6vn<m z@^mrbd;G~RzE#O`mE5IILZBdIuyP2Z<oOUsHmqp|6*@6dfS|7ZyAn@Ay#MVCK%7@0 zwj~6s(-akA`pt|U>`y{ND0+aOGg11hm?)~Z=vpc|>*_hg`?iug?32_-wq6xfVCjL~ zuH-sMQ32Hr?M%F2Q?Q$|_J&$IJkQB?-RUf88cpkJXjpV&K{ocP8psvf4~R?Z(({Zj zHBnm<d%V$uB&bLUtq3c*(9RoijFwZQF*fXC=>fv_Eu9O%b2Yo}<=}eFYBt)D7^fn+ z1XT!})HHGFsSvdEHqqr39kLsW?(N%(OlJu005621m`DYNC6S^+47HI4nhG`U=O~bQ zBN#|b%)O1FkD$2$I!f$j6ueL&G%0pRo;i(TDmD0HUH_>r{v2igQ@@fWb;yDm(WsfI zg_q%6(&}c!n@iB8qMra=DWaa?*DXH+=SFm;sm)4HkN@lc=O>Y&dmp636B7R*MX+ra zxtRk1-UIgw1CE8;{>s@`&Z4<=4z=-%$r6b!+T5>udhqrJ*fD$+>OzH(tqAj-TB~6O zAkI%aj#T6{>K~tW+^NOUO_0iI$7$Csw-;*nZ7OS^4vOB<sRbuRG+3#xwFXd8)JHi5 zczJtpL0ni|8h<X%rkoo2TEbqa(?VOh`Hs@H7>hAzU0_SN6sjq3YDF_RzF4-;H4d?# zZQQ^vO{}!3)((HtI)%N!Z!Nj?>emXLMoMn~1PG!6+iB2TT<`^Qu9$!57{({6sLyK1 zVQVh1W)V}%iduJ?umOhKi@mpliTA&K|63dkz+L8v6O~Oa^712!{8CMQ-rn0Ne$L-V z_h(hvy&n^GDPRtmaX!!Mr@)gBKW)p$<=gV%?89E{z5V{T!32JP<@MKoiR+0srvjat zm_ck&!B>j2OE1$7DnB3~w1O8?LkN4Z_x6XMVn;F{5L-M0(bz5$^YA_9pDwE-%N7z7 zLPzCsdolGy;dlb80TcwxZTXleT>L4CvP2u(6?qvQU{*rWDh{G~`J#a#VOl;6iK3;q zXKHo}PaMZlVK)QV%^?;mi^tiG9_A+Uy2~k?s_R^IVqx7&R8TYU&R{_7$GW&Qwa^L( z+8*z5+fzcDf*_&I9kAI@JbdLA+_ZHcmE0{MI&`KDYf$foM8RH6z4X-nKpYG`#nM~- z2+2pp)6;M6{chbyNLbN{qESHwBnnhatw4mmc%cFj>JPpgoz8YctP9LCc!8fnM@_8; z)kxw6YVc2_%zt7Cly8>H65lt~!498p&Y>(OuUG88BJ2fh_vAe#ynM^&o;@OWI^GnY z{BIKn8CHaY)G<MEw!wOs9lpRJI)nE*2?FdEwtHefuxNEBDKc1Nl6~2O^^|Q^mHBho zZKW>$X$H|3&UbIpmMY3gT?&R#cve^U#C~8TCsBNJ9G@1$eU~RnzZ7@u@uW@~RtHh) zX9p9gpJ>8HUuzhx8qGNlI5n}>5gfjqq5`G|7ee;4btJ1czc!1ug}l0DzOMAkSI$C| zq31T=$A#a<_zr`D{<)EZiNZpxk`zQ!<E})o!C(c1;01OZ{`d0V{JmIAfDqMroET~$ z?@DdaqTNlOY+3pggg#p3S#USiih+r0O1zT@5?3%$Vs&GVv|VX_WptygQi1XMDfgf) zJMT0gJf6jCaatd0IH^Gp8kgBw(kS+G&JWGM)|?~ap<ScRIbwB#igHfH$X_X=YmyL9 zDbtQ`y|6Uyi07Sl+ZV5et4T*1E^TOl<`!>Gg~sKGv?qPPjiHSkVk>Ff{iC3QR`-RC z8#nF&#PDDJ_tq2@LN~pB$~%~CqNEr1WI@H2r8sqP5=7>(H@x63Qd}Z_#)jSoo?j#3 z#YPW4hYppBab5@rMSeN%jV(Tp<8Yz5#Ic4?O_Zg-l@%89&FrB)EXi)<LHI<?IDY`4 zg^;K&;RZ~E2qtFLdnx@WPC0?lzV!)*_^#=@adum59Sl^YIn$iu5JzeXmXky;xSKnW z+N%ViRo6ud;^jE@@2g8s71~J<j5-Fa$0-s>9w-Ni+Cm%kYnJ+Tuoq8l-Ab-*>RL_q zos-lha>v_fp1btG0Xja1>+p{c2puJi$?hxgKvGns6bO$rgpOj%9soi;fcg3M0<Aqq z#67eh5IRbvQ-vB#K}=S4Dc7IQL3yzn{NKP{pq~~K5ue<+r0A#%PsSE_IBX(QKJ}RT z$dit0mx&t5c$a}rNgnE>B-z<giPP40Ur8R!B0IHH4>a-#Yfdo=KY7Z_ZTZYIZTanu z)DFjY&lpt*Fq&K*YPb|skl1n7FT7l)#VFC1jgJLK#otiB+f8`)JVPBv>e3s<_Hu8$ zqq?(`;%;7p&Y{NiCu&-&X>=9D?LGWImESl-adwHefJTY7m<E2*I4XV?g*93p=7;q+ zbtdFM-E>mc!69$FllHmwWKcz)UL}C&><pNFyqRe&AQlUsRzNr>+<h5A@cZWwrP`JK zrV8FzrkHDVgX^DIqV5NPu)7=E^V?|guE3Qxy^#psY0E!2Bp~Vmk+=H_FC+4a1Qo@c z4qR5e7bK}z+3)%lwOP8VmFha33Fn{+2%Oto-O-)Nmg5o^-b@5f1<d=(1cVO|Mh@{E z^t_=25UKkw;BO~U0A6e+XPMgdS#`MjE+9mY_mW$$@JBTego4DvrZtHmWph*r1rV}; zcq=5Rc)m2zxupa_^B<iEfvnWd{uBg+>B5_xozH>r>)v_%R>;YuPl~hWT%KyI>~GzH z(kh=Q4`_IKEe=v2pC|>L)|=K`>&T*1<IqG1NR;4(^a*+6!&8lw{U7(M?9Qjd{LO*I z7XdNOZiNbl?HAr`Yy-q40ns!<2kVWB7)WKevu~<V6#n>{Dzw#YIAjmGHMmGgp``;o zSmvfRmjV;0V7%*AEIl8Vym8@WXU$Z@!M8PwrRQ;h3b>;<sw%nk0AalF<|cpEMmjp5 zZx%KR?IaY456j;8dlU#$6^IRe&;g<9#}$Y|HHkMjt+}9Nt+{Y;NUZ1-#O^C%qW-7U z;GaO5{|WkOm8_BrVxm-Q;WJ`8zdC#f#D4EYP5q*NS|w{^-I@z;);Y6O)BiLC1@kXv zciW40B2xM>NyT|<mg*z<CT-U6@lKJFFQ&E^8sRE1vE@UYL#Db8CL4rSP~kK1i9+oT zz8)G*&<9C?^k5*__)^`}_9ATyZygJ%-NNdCl;yjz^aK@M+APXKnNXSrL~{-=@6soy zVvS10^X!GO!*UWO-Q-R~>|^AA;t&BS5J3g?V4+hUEkBqjgB2}VNI&?f4Ty0nrm`2= z9s$9`r4c;_Ok%4OGeu4sRVqSKmdjL8>NAqIC3ZLGY*?en%{c_fAxgfO+Flrr)1Ekj z&_{U^JYt~@<?7*$QrMTSQbGMqejRT?E&#-?dw}@)FKD8yf{N$sr$TzCTLlE2@DRa% zW8wmm;T%E}N>M>2ZNE;XLY*iSWvMbi2bYw5F}0>Ox&(wtoK)%(d=VY`de=A=bfDT| zMFt;M|MDqzYaz5R)lF?L+&&c|#b}k?W^OMy74Se5x$2^rs7XSLW|S9FQPm|xlzZx~ z)Ssb!?QL9WL50Fom7qdQ)WoG1OqizR1%{nJC<m9N<>nHFYO(aFqT}LA4^#kR;|3(& z!18Bx)Qc2|iTz#$0xGbwg}orl_eWKO|J(G_3d0KTCuJ`VJ=}jubQeh>A0CVG`zGoI zI}y=O%iRM6ernZAK;ZwA5Zd2kFZ|M(sUgsD$DJHnVrF44(1R-e<kunTDBJ@&^m$5q zLAy!lkQ?j)vP48jF!m!c9N0nCk*>6)t5%y+n<u6T61Drv=KBp4y8>bZ{567@+Fq~_ z8Y?G`Bt(GDZ*~KM+U5^$TK%}D(i}iG080-L8yn~mKD3B@&WTh!&t9O&uI@_b8-9iI zaGA(k&u;?+Wo<eyth%!DvCT#S%P5u}Y5@%wcI*HIJo7wG#Z>l!x&)o7F%o-<1w<x2 z$i@)^1g2-xYagt<=Q3p%Q<CTsnnbr=-PrK{x6m_yuyKf~?1kfu1>HmuTskwF88t;S zy8&Sd;pixWSPlqIg<qFljI_FdXt=QL7*4xV+3mdXyirJR2W<|V3S#CNf>;TNd!Pak zf)|)5P~nIfeJ_T<z}lEJQLfZPafw<Dh{vl(RzF66GfEt)MD5st_8$>WmJiRZm}-ne zOk%f*vztS#$0bJAkFFoVF(b&}q$J8}(D_AZ{~`!%fJ!+x*slnorOyENUlN44%O(W$ zvPf`=iE5&(8X&}KdC^2AA(Bha#Kh7QZX1V4Wj;1;fY1W!&_l#|ejN^JOSa*^K!KpX z|3U>K(kxJeYJ3q)079H0n$h!*Nwd7jB>k`2Py2_xs09lO8;yoD&sYtjAP8xgP~yi# zg<mvLFFt;k8p-6aE+U>k;I^;XfV28^esPSGdAw_xxn9I>N?CQhFmb1i*kX9tm{a@O zFAqJ0?3n0@a@fC_L1NgJFS5;QCg-{FMc8pfh-~uBk9I=t0Afo`eTJy>!L;Kjv|)=7 z%D6b~+waCXs0M3&-W*I6)$v|nFPO9aX?u}^IGN6@F(rW}7pHc?UHDPu!?SvG2UgMi zWDFU6yRQ@hf*yb{wY`u+P2Y_x5bpE~2&(+jsZ!){I=@y%!0uPh(%FEf9XpU=wi;H= z(|>IlGFlrNxPp07)Hk)gcnX3Ek5-&P&mwR*?=4T@#0wlo4JlS3f@7m)Zu_o#>%fbT zUSu!yk)~1Js4K#-h=35!-IKzAXkXPSHYf|BMY{`~Kxih2O9zKG-{-l*EYeX^#ut`o zQ$L4@a7`5z5d7>~+89X?%dfqAE~5wX?Y7ruQHPNhg<a}PX2xr6`Md6oLrm$JQ)M+j zsmQxC!;C9(a{x{G<UTWkSov^gKem;X?W-whZ^RLVcxY%aMi4S`F#=-V_Nn6wYVL?9 zAp&G0I0Wr6X~VON&FE!aJ=8RcM`eHtePr`}Je-oY&~@+p+UTLD!-ynn7L}i00O95K zf?JA!h%Pj=p@;`(5ZZMIDqC=1WZ6Cl?Xm}p*TUIyMA}v+R=7-U`2vE3ddm2M4hxLn zzJ;X_(FJ<N1OzR;>W<2mtXhC9-BQ`oG@9RrqZ3GdZ63Q1F&KxKa=ge|a0P;XGC>6( zL|YPX<gtk(j0D7s)ZmL7n0`b*?T=9AKlO`Ru++q1Y6#-J{DB=(s1`f=vVJ@S6?!s# zGW8R{YS6BVuuLlwPXN<a2ge~O(wG3DmN~#LaDn!WnOMuy7pCJcxUtiRDV)suN=wgw zfYqSKmqY*s@!baqUg)T0v^uh|jng8EAjwm%Xp;w?6-dwRqC*c_(8VcwCq+*#xtzTJ zPU|Q4;iWAGQeQI${M2=4h-xGCqkwoPLJ(0D3u}=q%A$MqTf%fwc?geLLIXZ+D1gL< zvJ^U$+bSS%+AFjiUwoWWy^|Ekifhw)?e5AJWh7w6R&jr#ID5feYT+3hBYUBb)FL&U zMVAlIaf^7m5UpD}X^DD<y=eG}=SJv&lv~1rW9L22*Wl;UD^P=(T?Fx3V?l@8zW<Wa zd2q-Xcf}Q|;TLDq!?2lV2wj{i1f7K!){za+M5;UV^r#T4!AXZhTeWk;Y(O(8Aix_( zY-TTfL2=-{rHfPX+LgBa{g;-XBeUA6&{j-9pkq@mTWYsN1qAlwv#^<th>*y=w1m*^ zgI-Oiw%9t8PMXpAA&2}>3zk<ePN0D=lL?cwKJmtV6h~H3llSs#O6T%(3+|TfLnTbU z)KQ&+pktA_t0TcW69g^~nDXedZv9gb=y(?GmJ%R*=1tUKwSC^ZpV0%b8<$^OwWBy2 zkM|&mYxIo!$T);w6Lm!CtbAlM!+0culRwEh(^o`iW=x(a^nR%gHU!Z+g00Fm1v~r8 zhhMw2qVe6&0Kuss_t{__hhQ2yThQ*-^CNipkw>t=abvgHU}2NkT`zR)I0UT4``>Q7 zU=Ebjy>YLm3`g6}z47j6tG|{#$lxc}Mbt(IA?YaFX2Gvc5ZcVZY&_s*qR{rjpH$DM zCJ1QS6)Rr*W!b*6eVaa5vkAv0SPk!fR=Yx8flZiVb@Qz#;fYHR8*S)d6uMs=!Z~T_ zbx%6=0r&$4{D)4>T&c{w000BoNkl<ZQS#eXtk{2v8u{oDl?`hauNAFSuosx!TKLw_ zQ6M6v1*x$<b5O@bw~Z7CsGx065uC@+*#6$C#cRdsxEh<=hQo*d2x{<8pv-@o7wY}+ z1|3nH)W?<X<UQSZ;aQ(zqF`7>=kmmhs5+I6cjQ7)MMD}KKkTz7AKyleWH~&-NEv&v zLcMW*@LCw`21M$a9w}uGRfuh9)ERC^)1u8LK5_pGFPmIxUFj!tZxR(n%ucpK^x0uR z``|9HCv{GjN(DDQT!u`b$AyEPWO@pZ77umkV5PFsG+NXrKH>Z?yqs>$?9S+^Xhu_C z$VLjB8mWfo597@P82Z1T|AHLJlk}we<V3;K#=U3I8Q?NMg{c$AiFdNI>}$3!t*dEt z!7%^4>xiYFEFaGB8La6ii;C%nS9aOH!bW#*TtH+OV{a57$dP;iH3*1l$K7_o(4kaa zi`S;n<ButsL5Bn8%F@Nm2j<?it}RR78U@5#pWx^~r#8cv(UaM|@I0xXH@jbXu>9P@ z%i?Swv{dHuhu}2l%s=hDmhKb~OKx>`N+FyhmDaQHaz+>KvuSwQgYr@7^0I;1qy?xi zYBZy#Y4qLCX7*<E;1SPw)N?r?Hhi_=z^Wa%@A<=+Ah#V5PHpSR{L{{J+LHo;cBv=O zWKA3F2Fmv3Dj7XEeRu8++9S|?FuE*a^ffeWX$Mead!CKhJOF@<o`nMhvF+=crSE>W z@bZGY^M^$@O6~wY=b!%hFPx3CvI7u1Iy;v=07Th789n|A9_H0F3Yg5UR#NUc&2;gl zGtLVLlPjm$z}Y<q5NprX=5ITONY5L`ba_08{IKDMx+tp4hqoaRJGSK3%rlrMdf+aY zOcS;2K@%o+G%YkcoZgkwOf5@!InBtS%<RpiQ(VyTnSOG~P2@|>KJ&~oc)}k<b>Zb# z=n*0a%lOm9Kcyp5c<_xrRIq#T+6<hLLF}fjIG{&P3uSc8@Rtu0#3y*VUSqqBCaS0p z$GN7ToDPV!$9B*GCr)iiUHLGToVD(=5YB1GE%fAza&u81KQqrGb|JzdWFTcVL1@!i zuHP8J#mn#F;B|WHQ;fubL;<6U9@);;Ue!gw3!H;8=jg)AGi?aVGP^BNqpyq(3KUzP z)TKuR!6dn$T4e06piFXJIGguH74?ZvY*k4OT6$}*&Z9G;<{T~C2Z&NF8ZAXoPAUX@ zMF0_fR)IiyK#5RiLf9$J1hR=wRs6*u1tN}p!1+Dm1RrVACWwq4k!E>T4O*h=-{4bp oOo>nMG&O#re%gsGSP}jI00~S$<(_&DQ~&?~07*qoM6N<$f<MG*aR2}S literal 0 HcmV?d00001 diff --git a/assets/monochrome-transparent_packed.png.import b/assets/monochrome-transparent_packed.png.import new file mode 100644 index 0000000..c2c08e1 --- /dev/null +++ b/assets/monochrome-transparent_packed.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b3w5cmqr6fbcw" +path="res://.godot/imported/monochrome-transparent_packed.png-18e62eb8a2e2f5e9aa845251a509b9bf.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/monochrome-transparent_packed.png" +dest_files=["res://.godot/imported/monochrome-transparent_packed.png-18e62eb8a2e2f5e9aa845251a509b9bf.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 diff --git a/project.godot b/project.godot index c18f767..32b6d1c 100644 --- a/project.godot +++ b/project.godot @@ -10,45 +10,18 @@ config_version=5 [application] -config/name="The Maze" -run/main_scene="res://src/special_scenes/game_handler.tscn" +config/name="the-maze" +run/main_scene="res://src/main/main.tscn" config/features=PackedStringArray("4.2", "GL Compatibility") config/icon="res://icon.svg" -[input] +[display] -ui_left={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194319,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"echo":false,"script":null) -] -} -ui_right={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194321,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null) -] -} -ui_up={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194320,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"echo":false,"script":null) -] -} -ui_down={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194322,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null) -] -} +window/size/viewport_width=256 +window/size/viewport_height=144 +window/size/window_width_override=1280 +window/size/window_height_override=720 +window/stretch/mode="viewport" [rendering] diff --git a/src/main/main.tscn b/src/main/main.tscn new file mode 100644 index 0000000..92c6fa0 --- /dev/null +++ b/src/main/main.tscn @@ -0,0 +1,3264 @@ +[gd_scene load_steps=6 format=3 uid="uid://cv5xm6ru2dkxf"] + +[ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] +[ext_resource type="PackedScene" uid="uid://bp6oyjqvoyffq" path="res://src/player/player.tscn" id="2_ekt33"] +[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="2_win2x"] + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ari5a"] +texture = ExtResource("1_kghfi") +1:0/0 = 0 +1:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:0/0/physics_layer_0/angular_velocity = 0.0 +2:0/0 = 0 +2:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:0/0/physics_layer_0/angular_velocity = 0.0 +3:0/0 = 0 +3:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:0/0/physics_layer_0/angular_velocity = 0.0 +4:0/0 = 0 +4:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:0/0/physics_layer_0/angular_velocity = 0.0 +5:0/0 = 0 +5:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:0/0/physics_layer_0/angular_velocity = 0.0 +6:0/0 = 0 +6:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:0/0/physics_layer_0/angular_velocity = 0.0 +7:0/0 = 0 +7:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:0/0/physics_layer_0/angular_velocity = 0.0 +8:0/0 = 0 +8:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:0/0/physics_layer_0/angular_velocity = 0.0 +9:0/0 = 0 +9:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:0/0/physics_layer_0/angular_velocity = 0.0 +10:0/0 = 0 +10:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:0/0/physics_layer_0/angular_velocity = 0.0 +11:0/0 = 0 +11:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:0/0/physics_layer_0/angular_velocity = 0.0 +12:0/0 = 0 +12:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:0/0/physics_layer_0/angular_velocity = 0.0 +13:0/0 = 0 +13:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:0/0/physics_layer_0/angular_velocity = 0.0 +14:0/0 = 0 +14:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:0/0/physics_layer_0/angular_velocity = 0.0 +15:0/0 = 0 +15:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:0/0/physics_layer_0/angular_velocity = 0.0 +16:0/0 = 0 +16:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:0/0/physics_layer_0/angular_velocity = 0.0 +17:0/0 = 0 +17:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:0/0/physics_layer_0/angular_velocity = 0.0 +19:0/0 = 0 +19:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:0/0/physics_layer_0/angular_velocity = 0.0 +19:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +20:0/0 = 0 +20:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:0/0/physics_layer_0/angular_velocity = 0.0 +20:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +21:0/0 = 0 +21:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:0/0/physics_layer_0/angular_velocity = 0.0 +22:0/0 = 0 +22:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:0/0/physics_layer_0/angular_velocity = 0.0 +23:0/0 = 0 +23:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:0/0/physics_layer_0/angular_velocity = 0.0 +24:0/0 = 0 +24:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:0/0/physics_layer_0/angular_velocity = 0.0 +25:0/0 = 0 +25:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:0/0/physics_layer_0/angular_velocity = 0.0 +26:0/0 = 0 +26:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:0/0/physics_layer_0/angular_velocity = 0.0 +27:0/0 = 0 +27:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:0/0/physics_layer_0/angular_velocity = 0.0 +28:0/0 = 0 +28:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:0/0/physics_layer_0/angular_velocity = 0.0 +29:0/0 = 0 +29:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:0/0/physics_layer_0/angular_velocity = 0.0 +30:0/0 = 0 +30:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:0/0/physics_layer_0/angular_velocity = 0.0 +31:0/0 = 0 +31:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:0/0/physics_layer_0/angular_velocity = 0.0 +32:0/0 = 0 +32:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:0/0/physics_layer_0/angular_velocity = 0.0 +33:0/0 = 0 +33:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:0/0/physics_layer_0/angular_velocity = 0.0 +34:0/0 = 0 +34:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:0/0/physics_layer_0/angular_velocity = 0.0 +35:0/0 = 0 +35:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:0/0/physics_layer_0/angular_velocity = 0.0 +36:0/0 = 0 +36:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:0/0/physics_layer_0/angular_velocity = 0.0 +37:0/0 = 0 +37:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:0/0/physics_layer_0/angular_velocity = 0.0 +38:0/0 = 0 +38:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:0/0/physics_layer_0/angular_velocity = 0.0 +39:0/0 = 0 +39:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:0/0/physics_layer_0/angular_velocity = 0.0 +40:0/0 = 0 +40:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:0/0/physics_layer_0/angular_velocity = 0.0 +41:0/0 = 0 +41:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:0/0/physics_layer_0/angular_velocity = 0.0 +42:0/0 = 0 +42:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:0/0/physics_layer_0/angular_velocity = 0.0 +43:0/0 = 0 +43:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:0/0/physics_layer_0/angular_velocity = 0.0 +44:0/0 = 0 +44:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:0/0/physics_layer_0/angular_velocity = 0.0 +45:0/0 = 0 +45:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:0/0/physics_layer_0/angular_velocity = 0.0 +46:0/0 = 0 +46:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:0/0/physics_layer_0/angular_velocity = 0.0 +47:0/0 = 0 +47:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:0/0/physics_layer_0/angular_velocity = 0.0 +48:0/0 = 0 +48:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:0/0/physics_layer_0/angular_velocity = 0.0 +0:1/0 = 0 +0:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:1/0/physics_layer_0/angular_velocity = 0.0 +1:1/0 = 0 +1:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:1/0/physics_layer_0/angular_velocity = 0.0 +2:1/0 = 0 +2:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:1/0/physics_layer_0/angular_velocity = 0.0 +3:1/0 = 0 +3:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:1/0/physics_layer_0/angular_velocity = 0.0 +4:1/0 = 0 +4:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:1/0/physics_layer_0/angular_velocity = 0.0 +5:1/0 = 0 +5:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:1/0/physics_layer_0/angular_velocity = 0.0 +6:1/0 = 0 +6:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:1/0/physics_layer_0/angular_velocity = 0.0 +7:1/0 = 0 +7:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:1/0/physics_layer_0/angular_velocity = 0.0 +8:1/0 = 0 +8:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:1/0/physics_layer_0/angular_velocity = 0.0 +9:1/0 = 0 +9:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:1/0/physics_layer_0/angular_velocity = 0.0 +10:1/0 = 0 +10:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:1/0/physics_layer_0/angular_velocity = 0.0 +11:1/0 = 0 +11:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:1/0/physics_layer_0/angular_velocity = 0.0 +12:1/0 = 0 +12:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:1/0/physics_layer_0/angular_velocity = 0.0 +13:1/0 = 0 +13:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:1/0/physics_layer_0/angular_velocity = 0.0 +14:1/0 = 0 +14:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:1/0/physics_layer_0/angular_velocity = 0.0 +15:1/0 = 0 +15:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:1/0/physics_layer_0/angular_velocity = 0.0 +16:1/0 = 0 +16:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:1/0/physics_layer_0/angular_velocity = 0.0 +17:1/0 = 0 +17:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:1/0/physics_layer_0/angular_velocity = 0.0 +18:1/0 = 0 +18:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:1/0/physics_layer_0/angular_velocity = 0.0 +18:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +19:1/0 = 0 +19:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:1/0/physics_layer_0/angular_velocity = 0.0 +20:1/0 = 0 +20:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:1/0/physics_layer_0/angular_velocity = 0.0 +20:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +21:1/0 = 0 +21:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:1/0/physics_layer_0/angular_velocity = 0.0 +22:1/0 = 0 +22:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:1/0/physics_layer_0/angular_velocity = 0.0 +23:1/0 = 0 +23:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:1/0/physics_layer_0/angular_velocity = 0.0 +24:1/0 = 0 +24:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:1/0/physics_layer_0/angular_velocity = 0.0 +25:1/0 = 0 +25:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:1/0/physics_layer_0/angular_velocity = 0.0 +26:1/0 = 0 +26:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:1/0/physics_layer_0/angular_velocity = 0.0 +27:1/0 = 0 +27:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:1/0/physics_layer_0/angular_velocity = 0.0 +28:1/0 = 0 +28:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:1/0/physics_layer_0/angular_velocity = 0.0 +29:1/0 = 0 +29:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:1/0/physics_layer_0/angular_velocity = 0.0 +30:1/0 = 0 +30:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:1/0/physics_layer_0/angular_velocity = 0.0 +31:1/0 = 0 +31:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:1/0/physics_layer_0/angular_velocity = 0.0 +32:1/0 = 0 +32:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:1/0/physics_layer_0/angular_velocity = 0.0 +33:1/0 = 0 +33:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:1/0/physics_layer_0/angular_velocity = 0.0 +34:1/0 = 0 +34:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:1/0/physics_layer_0/angular_velocity = 0.0 +35:1/0 = 0 +35:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:1/0/physics_layer_0/angular_velocity = 0.0 +36:1/0 = 0 +36:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:1/0/physics_layer_0/angular_velocity = 0.0 +37:1/0 = 0 +37:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:1/0/physics_layer_0/angular_velocity = 0.0 +38:1/0 = 0 +38:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:1/0/physics_layer_0/angular_velocity = 0.0 +39:1/0 = 0 +39:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:1/0/physics_layer_0/angular_velocity = 0.0 +40:1/0 = 0 +40:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:1/0/physics_layer_0/angular_velocity = 0.0 +41:1/0 = 0 +41:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:1/0/physics_layer_0/angular_velocity = 0.0 +42:1/0 = 0 +42:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:1/0/physics_layer_0/angular_velocity = 0.0 +43:1/0 = 0 +43:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:1/0/physics_layer_0/angular_velocity = 0.0 +44:1/0 = 0 +44:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:1/0/physics_layer_0/angular_velocity = 0.0 +45:1/0 = 0 +45:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:1/0/physics_layer_0/angular_velocity = 0.0 +46:1/0 = 0 +46:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:1/0/physics_layer_0/angular_velocity = 0.0 +47:1/0 = 0 +47:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:1/0/physics_layer_0/angular_velocity = 0.0 +48:1/0 = 0 +48:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:1/0/physics_layer_0/angular_velocity = 0.0 +0:2/0 = 0 +0:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:2/0/physics_layer_0/angular_velocity = 0.0 +1:2/0 = 0 +1:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:2/0/physics_layer_0/angular_velocity = 0.0 +2:2/0 = 0 +2:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:2/0/physics_layer_0/angular_velocity = 0.0 +3:2/0 = 0 +3:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:2/0/physics_layer_0/angular_velocity = 0.0 +4:2/0 = 0 +4:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:2/0/physics_layer_0/angular_velocity = 0.0 +5:2/0 = 0 +5:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:2/0/physics_layer_0/angular_velocity = 0.0 +6:2/0 = 0 +6:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:2/0/physics_layer_0/angular_velocity = 0.0 +7:2/0 = 0 +7:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:2/0/physics_layer_0/angular_velocity = 0.0 +8:2/0 = 0 +8:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:2/0/physics_layer_0/angular_velocity = 0.0 +9:2/0 = 0 +9:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:2/0/physics_layer_0/angular_velocity = 0.0 +10:2/0 = 0 +10:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:2/0/physics_layer_0/angular_velocity = 0.0 +11:2/0 = 0 +11:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:2/0/physics_layer_0/angular_velocity = 0.0 +12:2/0 = 0 +12:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:2/0/physics_layer_0/angular_velocity = 0.0 +13:2/0 = 0 +13:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:2/0/physics_layer_0/angular_velocity = 0.0 +14:2/0 = 0 +14:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:2/0/physics_layer_0/angular_velocity = 0.0 +15:2/0 = 0 +15:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:2/0/physics_layer_0/angular_velocity = 0.0 +16:2/0 = 0 +16:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:2/0/physics_layer_0/angular_velocity = 0.0 +17:2/0 = 0 +17:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:2/0/physics_layer_0/angular_velocity = 0.0 +18:2/0 = 0 +18:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:2/0/physics_layer_0/angular_velocity = 0.0 +18:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +19:2/0 = 0 +19:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:2/0/physics_layer_0/angular_velocity = 0.0 +19:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +20:2/0 = 0 +20:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:2/0/physics_layer_0/angular_velocity = 0.0 +20:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +21:2/0 = 0 +21:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:2/0/physics_layer_0/angular_velocity = 0.0 +22:2/0 = 0 +22:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:2/0/physics_layer_0/angular_velocity = 0.0 +23:2/0 = 0 +23:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:2/0/physics_layer_0/angular_velocity = 0.0 +24:2/0 = 0 +24:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:2/0/physics_layer_0/angular_velocity = 0.0 +25:2/0 = 0 +25:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:2/0/physics_layer_0/angular_velocity = 0.0 +26:2/0 = 0 +26:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:2/0/physics_layer_0/angular_velocity = 0.0 +27:2/0 = 0 +27:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:2/0/physics_layer_0/angular_velocity = 0.0 +28:2/0 = 0 +28:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:2/0/physics_layer_0/angular_velocity = 0.0 +29:2/0 = 0 +29:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:2/0/physics_layer_0/angular_velocity = 0.0 +30:2/0 = 0 +30:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:2/0/physics_layer_0/angular_velocity = 0.0 +31:2/0 = 0 +31:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:2/0/physics_layer_0/angular_velocity = 0.0 +32:2/0 = 0 +32:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:2/0/physics_layer_0/angular_velocity = 0.0 +33:2/0 = 0 +33:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:2/0/physics_layer_0/angular_velocity = 0.0 +34:2/0 = 0 +34:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:2/0/physics_layer_0/angular_velocity = 0.0 +35:2/0 = 0 +35:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:2/0/physics_layer_0/angular_velocity = 0.0 +36:2/0 = 0 +36:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:2/0/physics_layer_0/angular_velocity = 0.0 +37:2/0 = 0 +37:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:2/0/physics_layer_0/angular_velocity = 0.0 +38:2/0 = 0 +38:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:2/0/physics_layer_0/angular_velocity = 0.0 +39:2/0 = 0 +39:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:2/0/physics_layer_0/angular_velocity = 0.0 +40:2/0 = 0 +40:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:2/0/physics_layer_0/angular_velocity = 0.0 +41:2/0 = 0 +41:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:2/0/physics_layer_0/angular_velocity = 0.0 +42:2/0 = 0 +42:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:2/0/physics_layer_0/angular_velocity = 0.0 +43:2/0 = 0 +43:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:2/0/physics_layer_0/angular_velocity = 0.0 +44:2/0 = 0 +44:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:2/0/physics_layer_0/angular_velocity = 0.0 +45:2/0 = 0 +45:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:2/0/physics_layer_0/angular_velocity = 0.0 +46:2/0 = 0 +46:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:2/0/physics_layer_0/angular_velocity = 0.0 +47:2/0 = 0 +47:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:2/0/physics_layer_0/angular_velocity = 0.0 +48:2/0 = 0 +48:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:2/0/physics_layer_0/angular_velocity = 0.0 +0:3/0 = 0 +0:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:3/0/physics_layer_0/angular_velocity = 0.0 +1:3/0 = 0 +1:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:3/0/physics_layer_0/angular_velocity = 0.0 +2:3/0 = 0 +2:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:3/0/physics_layer_0/angular_velocity = 0.0 +3:3/0 = 0 +3:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:3/0/physics_layer_0/angular_velocity = 0.0 +4:3/0 = 0 +4:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:3/0/physics_layer_0/angular_velocity = 0.0 +5:3/0 = 0 +5:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:3/0/physics_layer_0/angular_velocity = 0.0 +6:3/0 = 0 +6:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:3/0/physics_layer_0/angular_velocity = 0.0 +7:3/0 = 0 +7:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:3/0/physics_layer_0/angular_velocity = 0.0 +8:3/0 = 0 +8:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:3/0/physics_layer_0/angular_velocity = 0.0 +9:3/0 = 0 +9:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:3/0/physics_layer_0/angular_velocity = 0.0 +10:3/0 = 0 +10:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:3/0/physics_layer_0/angular_velocity = 0.0 +11:3/0 = 0 +11:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:3/0/physics_layer_0/angular_velocity = 0.0 +12:3/0 = 0 +12:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:3/0/physics_layer_0/angular_velocity = 0.0 +13:3/0 = 0 +13:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:3/0/physics_layer_0/angular_velocity = 0.0 +14:3/0 = 0 +14:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:3/0/physics_layer_0/angular_velocity = 0.0 +15:3/0 = 0 +15:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:3/0/physics_layer_0/angular_velocity = 0.0 +16:3/0 = 0 +16:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:3/0/physics_layer_0/angular_velocity = 0.0 +17:3/0 = 0 +17:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:3/0/physics_layer_0/angular_velocity = 0.0 +18:3/0 = 0 +18:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:3/0/physics_layer_0/angular_velocity = 0.0 +19:3/0 = 0 +19:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:3/0/physics_layer_0/angular_velocity = 0.0 +20:3/0 = 0 +20:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:3/0/physics_layer_0/angular_velocity = 0.0 +21:3/0 = 0 +21:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:3/0/physics_layer_0/angular_velocity = 0.0 +22:3/0 = 0 +22:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:3/0/physics_layer_0/angular_velocity = 0.0 +23:3/0 = 0 +23:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:3/0/physics_layer_0/angular_velocity = 0.0 +24:3/0 = 0 +24:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:3/0/physics_layer_0/angular_velocity = 0.0 +25:3/0 = 0 +25:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:3/0/physics_layer_0/angular_velocity = 0.0 +26:3/0 = 0 +26:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:3/0/physics_layer_0/angular_velocity = 0.0 +27:3/0 = 0 +27:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:3/0/physics_layer_0/angular_velocity = 0.0 +28:3/0 = 0 +28:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:3/0/physics_layer_0/angular_velocity = 0.0 +29:3/0 = 0 +29:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:3/0/physics_layer_0/angular_velocity = 0.0 +30:3/0 = 0 +30:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:3/0/physics_layer_0/angular_velocity = 0.0 +31:3/0 = 0 +31:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:3/0/physics_layer_0/angular_velocity = 0.0 +32:3/0 = 0 +32:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:3/0/physics_layer_0/angular_velocity = 0.0 +33:3/0 = 0 +33:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:3/0/physics_layer_0/angular_velocity = 0.0 +34:3/0 = 0 +34:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:3/0/physics_layer_0/angular_velocity = 0.0 +35:3/0 = 0 +35:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:3/0/physics_layer_0/angular_velocity = 0.0 +36:3/0 = 0 +36:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:3/0/physics_layer_0/angular_velocity = 0.0 +37:3/0 = 0 +37:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:3/0/physics_layer_0/angular_velocity = 0.0 +38:3/0 = 0 +38:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:3/0/physics_layer_0/angular_velocity = 0.0 +39:3/0 = 0 +39:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:3/0/physics_layer_0/angular_velocity = 0.0 +40:3/0 = 0 +40:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:3/0/physics_layer_0/angular_velocity = 0.0 +41:3/0 = 0 +41:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:3/0/physics_layer_0/angular_velocity = 0.0 +42:3/0 = 0 +42:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:3/0/physics_layer_0/angular_velocity = 0.0 +43:3/0 = 0 +43:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:3/0/physics_layer_0/angular_velocity = 0.0 +44:3/0 = 0 +44:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:3/0/physics_layer_0/angular_velocity = 0.0 +45:3/0 = 0 +45:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:3/0/physics_layer_0/angular_velocity = 0.0 +46:3/0 = 0 +46:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:3/0/physics_layer_0/angular_velocity = 0.0 +47:3/0 = 0 +47:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:3/0/physics_layer_0/angular_velocity = 0.0 +48:3/0 = 0 +48:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:3/0/physics_layer_0/angular_velocity = 0.0 +0:4/0 = 0 +0:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:4/0/physics_layer_0/angular_velocity = 0.0 +1:4/0 = 0 +1:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:4/0/physics_layer_0/angular_velocity = 0.0 +2:4/0 = 0 +2:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:4/0/physics_layer_0/angular_velocity = 0.0 +3:4/0 = 0 +3:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:4/0/physics_layer_0/angular_velocity = 0.0 +4:4/0 = 0 +4:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:4/0/physics_layer_0/angular_velocity = 0.0 +5:4/0 = 0 +5:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:4/0/physics_layer_0/angular_velocity = 0.0 +6:4/0 = 0 +6:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:4/0/physics_layer_0/angular_velocity = 0.0 +7:4/0 = 0 +7:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:4/0/physics_layer_0/angular_velocity = 0.0 +8:4/0 = 0 +8:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:4/0/physics_layer_0/angular_velocity = 0.0 +9:4/0 = 0 +9:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:4/0/physics_layer_0/angular_velocity = 0.0 +10:4/0 = 0 +10:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:4/0/physics_layer_0/angular_velocity = 0.0 +11:4/0 = 0 +11:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:4/0/physics_layer_0/angular_velocity = 0.0 +12:4/0 = 0 +12:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:4/0/physics_layer_0/angular_velocity = 0.0 +13:4/0 = 0 +13:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:4/0/physics_layer_0/angular_velocity = 0.0 +14:4/0 = 0 +14:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:4/0/physics_layer_0/angular_velocity = 0.0 +15:4/0 = 0 +15:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:4/0/physics_layer_0/angular_velocity = 0.0 +16:4/0 = 0 +16:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:4/0/physics_layer_0/angular_velocity = 0.0 +17:4/0 = 0 +17:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:4/0/physics_layer_0/angular_velocity = 0.0 +18:4/0 = 0 +18:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:4/0/physics_layer_0/angular_velocity = 0.0 +19:4/0 = 0 +19:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:4/0/physics_layer_0/angular_velocity = 0.0 +20:4/0 = 0 +20:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:4/0/physics_layer_0/angular_velocity = 0.0 +21:4/0 = 0 +21:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:4/0/physics_layer_0/angular_velocity = 0.0 +22:4/0 = 0 +22:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:4/0/physics_layer_0/angular_velocity = 0.0 +23:4/0 = 0 +23:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:4/0/physics_layer_0/angular_velocity = 0.0 +24:4/0 = 0 +24:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:4/0/physics_layer_0/angular_velocity = 0.0 +25:4/0 = 0 +25:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:4/0/physics_layer_0/angular_velocity = 0.0 +26:4/0 = 0 +26:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:4/0/physics_layer_0/angular_velocity = 0.0 +27:4/0 = 0 +27:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:4/0/physics_layer_0/angular_velocity = 0.0 +28:4/0 = 0 +28:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:4/0/physics_layer_0/angular_velocity = 0.0 +29:4/0 = 0 +29:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:4/0/physics_layer_0/angular_velocity = 0.0 +30:4/0 = 0 +30:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:4/0/physics_layer_0/angular_velocity = 0.0 +31:4/0 = 0 +31:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:4/0/physics_layer_0/angular_velocity = 0.0 +32:4/0 = 0 +32:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:4/0/physics_layer_0/angular_velocity = 0.0 +33:4/0 = 0 +33:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:4/0/physics_layer_0/angular_velocity = 0.0 +34:4/0 = 0 +34:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:4/0/physics_layer_0/angular_velocity = 0.0 +35:4/0 = 0 +35:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:4/0/physics_layer_0/angular_velocity = 0.0 +36:4/0 = 0 +36:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:4/0/physics_layer_0/angular_velocity = 0.0 +37:4/0 = 0 +37:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:4/0/physics_layer_0/angular_velocity = 0.0 +38:4/0 = 0 +38:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:4/0/physics_layer_0/angular_velocity = 0.0 +39:4/0 = 0 +39:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:4/0/physics_layer_0/angular_velocity = 0.0 +40:4/0 = 0 +40:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:4/0/physics_layer_0/angular_velocity = 0.0 +41:4/0 = 0 +41:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:4/0/physics_layer_0/angular_velocity = 0.0 +42:4/0 = 0 +42:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:4/0/physics_layer_0/angular_velocity = 0.0 +43:4/0 = 0 +43:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:4/0/physics_layer_0/angular_velocity = 0.0 +44:4/0 = 0 +44:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:4/0/physics_layer_0/angular_velocity = 0.0 +45:4/0 = 0 +45:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:4/0/physics_layer_0/angular_velocity = 0.0 +46:4/0 = 0 +46:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:4/0/physics_layer_0/angular_velocity = 0.0 +47:4/0 = 0 +47:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:4/0/physics_layer_0/angular_velocity = 0.0 +48:4/0 = 0 +48:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:4/0/physics_layer_0/angular_velocity = 0.0 +0:5/0 = 0 +0:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:5/0/physics_layer_0/angular_velocity = 0.0 +1:5/0 = 0 +1:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:5/0/physics_layer_0/angular_velocity = 0.0 +2:5/0 = 0 +2:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:5/0/physics_layer_0/angular_velocity = 0.0 +3:5/0 = 0 +3:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:5/0/physics_layer_0/angular_velocity = 0.0 +4:5/0 = 0 +4:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:5/0/physics_layer_0/angular_velocity = 0.0 +5:5/0 = 0 +5:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:5/0/physics_layer_0/angular_velocity = 0.0 +6:5/0 = 0 +6:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:5/0/physics_layer_0/angular_velocity = 0.0 +7:5/0 = 0 +7:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:5/0/physics_layer_0/angular_velocity = 0.0 +8:5/0 = 0 +8:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:5/0/physics_layer_0/angular_velocity = 0.0 +9:5/0 = 0 +9:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:5/0/physics_layer_0/angular_velocity = 0.0 +10:5/0 = 0 +10:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:5/0/physics_layer_0/angular_velocity = 0.0 +11:5/0 = 0 +11:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:5/0/physics_layer_0/angular_velocity = 0.0 +12:5/0 = 0 +12:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:5/0/physics_layer_0/angular_velocity = 0.0 +13:5/0 = 0 +13:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:5/0/physics_layer_0/angular_velocity = 0.0 +14:5/0 = 0 +14:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:5/0/physics_layer_0/angular_velocity = 0.0 +15:5/0 = 0 +15:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:5/0/physics_layer_0/angular_velocity = 0.0 +16:5/0 = 0 +16:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:5/0/physics_layer_0/angular_velocity = 0.0 +17:5/0 = 0 +17:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:5/0/physics_layer_0/angular_velocity = 0.0 +18:5/0 = 0 +18:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:5/0/physics_layer_0/angular_velocity = 0.0 +19:5/0 = 0 +19:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:5/0/physics_layer_0/angular_velocity = 0.0 +20:5/0 = 0 +20:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:5/0/physics_layer_0/angular_velocity = 0.0 +21:5/0 = 0 +21:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:5/0/physics_layer_0/angular_velocity = 0.0 +22:5/0 = 0 +22:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:5/0/physics_layer_0/angular_velocity = 0.0 +23:5/0 = 0 +23:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:5/0/physics_layer_0/angular_velocity = 0.0 +24:5/0 = 0 +24:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:5/0/physics_layer_0/angular_velocity = 0.0 +25:5/0 = 0 +25:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:5/0/physics_layer_0/angular_velocity = 0.0 +26:5/0 = 0 +26:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:5/0/physics_layer_0/angular_velocity = 0.0 +27:5/0 = 0 +27:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:5/0/physics_layer_0/angular_velocity = 0.0 +28:5/0 = 0 +28:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:5/0/physics_layer_0/angular_velocity = 0.0 +29:5/0 = 0 +29:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:5/0/physics_layer_0/angular_velocity = 0.0 +30:5/0 = 0 +30:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:5/0/physics_layer_0/angular_velocity = 0.0 +31:5/0 = 0 +31:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:5/0/physics_layer_0/angular_velocity = 0.0 +32:5/0 = 0 +32:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:5/0/physics_layer_0/angular_velocity = 0.0 +33:5/0 = 0 +33:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:5/0/physics_layer_0/angular_velocity = 0.0 +34:5/0 = 0 +34:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:5/0/physics_layer_0/angular_velocity = 0.0 +35:5/0 = 0 +35:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:5/0/physics_layer_0/angular_velocity = 0.0 +36:5/0 = 0 +36:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:5/0/physics_layer_0/angular_velocity = 0.0 +37:5/0 = 0 +37:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:5/0/physics_layer_0/angular_velocity = 0.0 +38:5/0 = 0 +38:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:5/0/physics_layer_0/angular_velocity = 0.0 +39:5/0 = 0 +39:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:5/0/physics_layer_0/angular_velocity = 0.0 +40:5/0 = 0 +40:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:5/0/physics_layer_0/angular_velocity = 0.0 +41:5/0 = 0 +41:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:5/0/physics_layer_0/angular_velocity = 0.0 +42:5/0 = 0 +42:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:5/0/physics_layer_0/angular_velocity = 0.0 +43:5/0 = 0 +43:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:5/0/physics_layer_0/angular_velocity = 0.0 +44:5/0 = 0 +44:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:5/0/physics_layer_0/angular_velocity = 0.0 +45:5/0 = 0 +45:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:5/0/physics_layer_0/angular_velocity = 0.0 +46:5/0 = 0 +46:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:5/0/physics_layer_0/angular_velocity = 0.0 +47:5/0 = 0 +47:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:5/0/physics_layer_0/angular_velocity = 0.0 +48:5/0 = 0 +48:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:5/0/physics_layer_0/angular_velocity = 0.0 +0:6/0 = 0 +0:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:6/0/physics_layer_0/angular_velocity = 0.0 +1:6/0 = 0 +1:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:6/0/physics_layer_0/angular_velocity = 0.0 +2:6/0 = 0 +2:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:6/0/physics_layer_0/angular_velocity = 0.0 +3:6/0 = 0 +3:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:6/0/physics_layer_0/angular_velocity = 0.0 +4:6/0 = 0 +4:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:6/0/physics_layer_0/angular_velocity = 0.0 +5:6/0 = 0 +5:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:6/0/physics_layer_0/angular_velocity = 0.0 +6:6/0 = 0 +6:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:6/0/physics_layer_0/angular_velocity = 0.0 +7:6/0 = 0 +7:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:6/0/physics_layer_0/angular_velocity = 0.0 +8:6/0 = 0 +8:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:6/0/physics_layer_0/angular_velocity = 0.0 +9:6/0 = 0 +9:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:6/0/physics_layer_0/angular_velocity = 0.0 +10:6/0 = 0 +10:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:6/0/physics_layer_0/angular_velocity = 0.0 +11:6/0 = 0 +11:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:6/0/physics_layer_0/angular_velocity = 0.0 +12:6/0 = 0 +12:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:6/0/physics_layer_0/angular_velocity = 0.0 +13:6/0 = 0 +13:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:6/0/physics_layer_0/angular_velocity = 0.0 +14:6/0 = 0 +14:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:6/0/physics_layer_0/angular_velocity = 0.0 +15:6/0 = 0 +15:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:6/0/physics_layer_0/angular_velocity = 0.0 +16:6/0 = 0 +16:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:6/0/physics_layer_0/angular_velocity = 0.0 +17:6/0 = 0 +17:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:6/0/physics_layer_0/angular_velocity = 0.0 +18:6/0 = 0 +18:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:6/0/physics_layer_0/angular_velocity = 0.0 +19:6/0 = 0 +19:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:6/0/physics_layer_0/angular_velocity = 0.0 +20:6/0 = 0 +20:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:6/0/physics_layer_0/angular_velocity = 0.0 +21:6/0 = 0 +21:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:6/0/physics_layer_0/angular_velocity = 0.0 +22:6/0 = 0 +22:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:6/0/physics_layer_0/angular_velocity = 0.0 +23:6/0 = 0 +23:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:6/0/physics_layer_0/angular_velocity = 0.0 +24:6/0 = 0 +24:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:6/0/physics_layer_0/angular_velocity = 0.0 +25:6/0 = 0 +25:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:6/0/physics_layer_0/angular_velocity = 0.0 +26:6/0 = 0 +26:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:6/0/physics_layer_0/angular_velocity = 0.0 +27:6/0 = 0 +27:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:6/0/physics_layer_0/angular_velocity = 0.0 +28:6/0 = 0 +28:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:6/0/physics_layer_0/angular_velocity = 0.0 +29:6/0 = 0 +29:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:6/0/physics_layer_0/angular_velocity = 0.0 +30:6/0 = 0 +30:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:6/0/physics_layer_0/angular_velocity = 0.0 +31:6/0 = 0 +31:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:6/0/physics_layer_0/angular_velocity = 0.0 +32:6/0 = 0 +32:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:6/0/physics_layer_0/angular_velocity = 0.0 +33:6/0 = 0 +33:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:6/0/physics_layer_0/angular_velocity = 0.0 +34:6/0 = 0 +34:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:6/0/physics_layer_0/angular_velocity = 0.0 +35:6/0 = 0 +35:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:6/0/physics_layer_0/angular_velocity = 0.0 +36:6/0 = 0 +36:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:6/0/physics_layer_0/angular_velocity = 0.0 +37:6/0 = 0 +37:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:6/0/physics_layer_0/angular_velocity = 0.0 +38:6/0 = 0 +38:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:6/0/physics_layer_0/angular_velocity = 0.0 +39:6/0 = 0 +39:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:6/0/physics_layer_0/angular_velocity = 0.0 +40:6/0 = 0 +40:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:6/0/physics_layer_0/angular_velocity = 0.0 +41:6/0 = 0 +41:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:6/0/physics_layer_0/angular_velocity = 0.0 +42:6/0 = 0 +42:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:6/0/physics_layer_0/angular_velocity = 0.0 +43:6/0 = 0 +43:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:6/0/physics_layer_0/angular_velocity = 0.0 +44:6/0 = 0 +44:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:6/0/physics_layer_0/angular_velocity = 0.0 +45:6/0 = 0 +45:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:6/0/physics_layer_0/angular_velocity = 0.0 +46:6/0 = 0 +46:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:6/0/physics_layer_0/angular_velocity = 0.0 +47:6/0 = 0 +47:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:6/0/physics_layer_0/angular_velocity = 0.0 +48:6/0 = 0 +48:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:6/0/physics_layer_0/angular_velocity = 0.0 +0:7/0 = 0 +0:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:7/0/physics_layer_0/angular_velocity = 0.0 +1:7/0 = 0 +1:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:7/0/physics_layer_0/angular_velocity = 0.0 +2:7/0 = 0 +2:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:7/0/physics_layer_0/angular_velocity = 0.0 +3:7/0 = 0 +3:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:7/0/physics_layer_0/angular_velocity = 0.0 +4:7/0 = 0 +4:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:7/0/physics_layer_0/angular_velocity = 0.0 +5:7/0 = 0 +5:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:7/0/physics_layer_0/angular_velocity = 0.0 +6:7/0 = 0 +6:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:7/0/physics_layer_0/angular_velocity = 0.0 +7:7/0 = 0 +7:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:7/0/physics_layer_0/angular_velocity = 0.0 +8:7/0 = 0 +8:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:7/0/physics_layer_0/angular_velocity = 0.0 +9:7/0 = 0 +9:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:7/0/physics_layer_0/angular_velocity = 0.0 +10:7/0 = 0 +10:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:7/0/physics_layer_0/angular_velocity = 0.0 +11:7/0 = 0 +11:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:7/0/physics_layer_0/angular_velocity = 0.0 +12:7/0 = 0 +12:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:7/0/physics_layer_0/angular_velocity = 0.0 +13:7/0 = 0 +13:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:7/0/physics_layer_0/angular_velocity = 0.0 +14:7/0 = 0 +14:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:7/0/physics_layer_0/angular_velocity = 0.0 +15:7/0 = 0 +15:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:7/0/physics_layer_0/angular_velocity = 0.0 +16:7/0 = 0 +16:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:7/0/physics_layer_0/angular_velocity = 0.0 +17:7/0 = 0 +17:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:7/0/physics_layer_0/angular_velocity = 0.0 +18:7/0 = 0 +18:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:7/0/physics_layer_0/angular_velocity = 0.0 +19:7/0 = 0 +19:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:7/0/physics_layer_0/angular_velocity = 0.0 +20:7/0 = 0 +20:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:7/0/physics_layer_0/angular_velocity = 0.0 +21:7/0 = 0 +21:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:7/0/physics_layer_0/angular_velocity = 0.0 +22:7/0 = 0 +22:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:7/0/physics_layer_0/angular_velocity = 0.0 +23:7/0 = 0 +23:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:7/0/physics_layer_0/angular_velocity = 0.0 +24:7/0 = 0 +24:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:7/0/physics_layer_0/angular_velocity = 0.0 +25:7/0 = 0 +25:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:7/0/physics_layer_0/angular_velocity = 0.0 +26:7/0 = 0 +26:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:7/0/physics_layer_0/angular_velocity = 0.0 +27:7/0 = 0 +27:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:7/0/physics_layer_0/angular_velocity = 0.0 +28:7/0 = 0 +28:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:7/0/physics_layer_0/angular_velocity = 0.0 +29:7/0 = 0 +29:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:7/0/physics_layer_0/angular_velocity = 0.0 +30:7/0 = 0 +30:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:7/0/physics_layer_0/angular_velocity = 0.0 +31:7/0 = 0 +31:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:7/0/physics_layer_0/angular_velocity = 0.0 +32:7/0 = 0 +32:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:7/0/physics_layer_0/angular_velocity = 0.0 +33:7/0 = 0 +33:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:7/0/physics_layer_0/angular_velocity = 0.0 +34:7/0 = 0 +34:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:7/0/physics_layer_0/angular_velocity = 0.0 +35:7/0 = 0 +35:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:7/0/physics_layer_0/angular_velocity = 0.0 +36:7/0 = 0 +36:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:7/0/physics_layer_0/angular_velocity = 0.0 +37:7/0 = 0 +37:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:7/0/physics_layer_0/angular_velocity = 0.0 +38:7/0 = 0 +38:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:7/0/physics_layer_0/angular_velocity = 0.0 +39:7/0 = 0 +39:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:7/0/physics_layer_0/angular_velocity = 0.0 +40:7/0 = 0 +40:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:7/0/physics_layer_0/angular_velocity = 0.0 +41:7/0 = 0 +41:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:7/0/physics_layer_0/angular_velocity = 0.0 +42:7/0 = 0 +42:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:7/0/physics_layer_0/angular_velocity = 0.0 +43:7/0 = 0 +43:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:7/0/physics_layer_0/angular_velocity = 0.0 +44:7/0 = 0 +44:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:7/0/physics_layer_0/angular_velocity = 0.0 +45:7/0 = 0 +45:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:7/0/physics_layer_0/angular_velocity = 0.0 +46:7/0 = 0 +46:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:7/0/physics_layer_0/angular_velocity = 0.0 +47:7/0 = 0 +47:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:7/0/physics_layer_0/angular_velocity = 0.0 +48:7/0 = 0 +48:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:7/0/physics_layer_0/angular_velocity = 0.0 +0:8/0 = 0 +0:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:8/0/physics_layer_0/angular_velocity = 0.0 +1:8/0 = 0 +1:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:8/0/physics_layer_0/angular_velocity = 0.0 +2:8/0 = 0 +2:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:8/0/physics_layer_0/angular_velocity = 0.0 +3:8/0 = 0 +3:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:8/0/physics_layer_0/angular_velocity = 0.0 +4:8/0 = 0 +4:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:8/0/physics_layer_0/angular_velocity = 0.0 +5:8/0 = 0 +5:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:8/0/physics_layer_0/angular_velocity = 0.0 +6:8/0 = 0 +6:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:8/0/physics_layer_0/angular_velocity = 0.0 +7:8/0 = 0 +7:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:8/0/physics_layer_0/angular_velocity = 0.0 +8:8/0 = 0 +8:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:8/0/physics_layer_0/angular_velocity = 0.0 +9:8/0 = 0 +9:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:8/0/physics_layer_0/angular_velocity = 0.0 +10:8/0 = 0 +10:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:8/0/physics_layer_0/angular_velocity = 0.0 +11:8/0 = 0 +11:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:8/0/physics_layer_0/angular_velocity = 0.0 +12:8/0 = 0 +12:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:8/0/physics_layer_0/angular_velocity = 0.0 +13:8/0 = 0 +13:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:8/0/physics_layer_0/angular_velocity = 0.0 +14:8/0 = 0 +14:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:8/0/physics_layer_0/angular_velocity = 0.0 +15:8/0 = 0 +15:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:8/0/physics_layer_0/angular_velocity = 0.0 +16:8/0 = 0 +16:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:8/0/physics_layer_0/angular_velocity = 0.0 +17:8/0 = 0 +17:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:8/0/physics_layer_0/angular_velocity = 0.0 +18:8/0 = 0 +18:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:8/0/physics_layer_0/angular_velocity = 0.0 +19:8/0 = 0 +19:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:8/0/physics_layer_0/angular_velocity = 0.0 +20:8/0 = 0 +20:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:8/0/physics_layer_0/angular_velocity = 0.0 +21:8/0 = 0 +21:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:8/0/physics_layer_0/angular_velocity = 0.0 +22:8/0 = 0 +22:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:8/0/physics_layer_0/angular_velocity = 0.0 +23:8/0 = 0 +23:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:8/0/physics_layer_0/angular_velocity = 0.0 +24:8/0 = 0 +24:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:8/0/physics_layer_0/angular_velocity = 0.0 +25:8/0 = 0 +25:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:8/0/physics_layer_0/angular_velocity = 0.0 +26:8/0 = 0 +26:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:8/0/physics_layer_0/angular_velocity = 0.0 +27:8/0 = 0 +27:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:8/0/physics_layer_0/angular_velocity = 0.0 +28:8/0 = 0 +28:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:8/0/physics_layer_0/angular_velocity = 0.0 +29:8/0 = 0 +29:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:8/0/physics_layer_0/angular_velocity = 0.0 +30:8/0 = 0 +30:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:8/0/physics_layer_0/angular_velocity = 0.0 +31:8/0 = 0 +31:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:8/0/physics_layer_0/angular_velocity = 0.0 +32:8/0 = 0 +32:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:8/0/physics_layer_0/angular_velocity = 0.0 +33:8/0 = 0 +33:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:8/0/physics_layer_0/angular_velocity = 0.0 +34:8/0 = 0 +34:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:8/0/physics_layer_0/angular_velocity = 0.0 +35:8/0 = 0 +35:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:8/0/physics_layer_0/angular_velocity = 0.0 +36:8/0 = 0 +36:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:8/0/physics_layer_0/angular_velocity = 0.0 +37:8/0 = 0 +37:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:8/0/physics_layer_0/angular_velocity = 0.0 +38:8/0 = 0 +38:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:8/0/physics_layer_0/angular_velocity = 0.0 +39:8/0 = 0 +39:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:8/0/physics_layer_0/angular_velocity = 0.0 +40:8/0 = 0 +40:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:8/0/physics_layer_0/angular_velocity = 0.0 +41:8/0 = 0 +41:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:8/0/physics_layer_0/angular_velocity = 0.0 +42:8/0 = 0 +42:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:8/0/physics_layer_0/angular_velocity = 0.0 +43:8/0 = 0 +43:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:8/0/physics_layer_0/angular_velocity = 0.0 +44:8/0 = 0 +44:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:8/0/physics_layer_0/angular_velocity = 0.0 +45:8/0 = 0 +45:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:8/0/physics_layer_0/angular_velocity = 0.0 +46:8/0 = 0 +46:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:8/0/physics_layer_0/angular_velocity = 0.0 +47:8/0 = 0 +47:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:8/0/physics_layer_0/angular_velocity = 0.0 +48:8/0 = 0 +48:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:8/0/physics_layer_0/angular_velocity = 0.0 +0:9/0 = 0 +0:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:9/0/physics_layer_0/angular_velocity = 0.0 +1:9/0 = 0 +1:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:9/0/physics_layer_0/angular_velocity = 0.0 +2:9/0 = 0 +2:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:9/0/physics_layer_0/angular_velocity = 0.0 +3:9/0 = 0 +3:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:9/0/physics_layer_0/angular_velocity = 0.0 +4:9/0 = 0 +4:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:9/0/physics_layer_0/angular_velocity = 0.0 +5:9/0 = 0 +5:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:9/0/physics_layer_0/angular_velocity = 0.0 +6:9/0 = 0 +6:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:9/0/physics_layer_0/angular_velocity = 0.0 +7:9/0 = 0 +7:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:9/0/physics_layer_0/angular_velocity = 0.0 +8:9/0 = 0 +8:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:9/0/physics_layer_0/angular_velocity = 0.0 +9:9/0 = 0 +9:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:9/0/physics_layer_0/angular_velocity = 0.0 +10:9/0 = 0 +10:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:9/0/physics_layer_0/angular_velocity = 0.0 +11:9/0 = 0 +11:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:9/0/physics_layer_0/angular_velocity = 0.0 +12:9/0 = 0 +12:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:9/0/physics_layer_0/angular_velocity = 0.0 +13:9/0 = 0 +13:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:9/0/physics_layer_0/angular_velocity = 0.0 +14:9/0 = 0 +14:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:9/0/physics_layer_0/angular_velocity = 0.0 +15:9/0 = 0 +15:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:9/0/physics_layer_0/angular_velocity = 0.0 +16:9/0 = 0 +16:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:9/0/physics_layer_0/angular_velocity = 0.0 +17:9/0 = 0 +17:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:9/0/physics_layer_0/angular_velocity = 0.0 +18:9/0 = 0 +18:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:9/0/physics_layer_0/angular_velocity = 0.0 +19:9/0 = 0 +19:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:9/0/physics_layer_0/angular_velocity = 0.0 +20:9/0 = 0 +20:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:9/0/physics_layer_0/angular_velocity = 0.0 +21:9/0 = 0 +21:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:9/0/physics_layer_0/angular_velocity = 0.0 +22:9/0 = 0 +22:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:9/0/physics_layer_0/angular_velocity = 0.0 +23:9/0 = 0 +23:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:9/0/physics_layer_0/angular_velocity = 0.0 +24:9/0 = 0 +24:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:9/0/physics_layer_0/angular_velocity = 0.0 +25:9/0 = 0 +25:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:9/0/physics_layer_0/angular_velocity = 0.0 +26:9/0 = 0 +26:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:9/0/physics_layer_0/angular_velocity = 0.0 +27:9/0 = 0 +27:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:9/0/physics_layer_0/angular_velocity = 0.0 +28:9/0 = 0 +28:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:9/0/physics_layer_0/angular_velocity = 0.0 +29:9/0 = 0 +29:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:9/0/physics_layer_0/angular_velocity = 0.0 +30:9/0 = 0 +30:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:9/0/physics_layer_0/angular_velocity = 0.0 +31:9/0 = 0 +31:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:9/0/physics_layer_0/angular_velocity = 0.0 +32:9/0 = 0 +32:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:9/0/physics_layer_0/angular_velocity = 0.0 +33:9/0 = 0 +33:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:9/0/physics_layer_0/angular_velocity = 0.0 +34:9/0 = 0 +34:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:9/0/physics_layer_0/angular_velocity = 0.0 +35:9/0 = 0 +35:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:9/0/physics_layer_0/angular_velocity = 0.0 +36:9/0 = 0 +36:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:9/0/physics_layer_0/angular_velocity = 0.0 +37:9/0 = 0 +37:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:9/0/physics_layer_0/angular_velocity = 0.0 +38:9/0 = 0 +38:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:9/0/physics_layer_0/angular_velocity = 0.0 +39:9/0 = 0 +39:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:9/0/physics_layer_0/angular_velocity = 0.0 +40:9/0 = 0 +40:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:9/0/physics_layer_0/angular_velocity = 0.0 +41:9/0 = 0 +41:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:9/0/physics_layer_0/angular_velocity = 0.0 +42:9/0 = 0 +42:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:9/0/physics_layer_0/angular_velocity = 0.0 +43:9/0 = 0 +43:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:9/0/physics_layer_0/angular_velocity = 0.0 +44:9/0 = 0 +44:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:9/0/physics_layer_0/angular_velocity = 0.0 +45:9/0 = 0 +45:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:9/0/physics_layer_0/angular_velocity = 0.0 +46:9/0 = 0 +46:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:9/0/physics_layer_0/angular_velocity = 0.0 +47:9/0 = 0 +47:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:9/0/physics_layer_0/angular_velocity = 0.0 +48:9/0 = 0 +48:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:9/0/physics_layer_0/angular_velocity = 0.0 +0:10/0 = 0 +0:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:10/0/physics_layer_0/angular_velocity = 0.0 +1:10/0 = 0 +1:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:10/0/physics_layer_0/angular_velocity = 0.0 +2:10/0 = 0 +2:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:10/0/physics_layer_0/angular_velocity = 0.0 +3:10/0 = 0 +3:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:10/0/physics_layer_0/angular_velocity = 0.0 +4:10/0 = 0 +4:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:10/0/physics_layer_0/angular_velocity = 0.0 +5:10/0 = 0 +5:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:10/0/physics_layer_0/angular_velocity = 0.0 +6:10/0 = 0 +6:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:10/0/physics_layer_0/angular_velocity = 0.0 +7:10/0 = 0 +7:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:10/0/physics_layer_0/angular_velocity = 0.0 +8:10/0 = 0 +8:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:10/0/physics_layer_0/angular_velocity = 0.0 +9:10/0 = 0 +9:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:10/0/physics_layer_0/angular_velocity = 0.0 +10:10/0 = 0 +10:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:10/0/physics_layer_0/angular_velocity = 0.0 +11:10/0 = 0 +11:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:10/0/physics_layer_0/angular_velocity = 0.0 +12:10/0 = 0 +12:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:10/0/physics_layer_0/angular_velocity = 0.0 +13:10/0 = 0 +13:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:10/0/physics_layer_0/angular_velocity = 0.0 +14:10/0 = 0 +14:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:10/0/physics_layer_0/angular_velocity = 0.0 +15:10/0 = 0 +15:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:10/0/physics_layer_0/angular_velocity = 0.0 +16:10/0 = 0 +16:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:10/0/physics_layer_0/angular_velocity = 0.0 +17:10/0 = 0 +17:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:10/0/physics_layer_0/angular_velocity = 0.0 +18:10/0 = 0 +18:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:10/0/physics_layer_0/angular_velocity = 0.0 +19:10/0 = 0 +19:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:10/0/physics_layer_0/angular_velocity = 0.0 +20:10/0 = 0 +20:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:10/0/physics_layer_0/angular_velocity = 0.0 +21:10/0 = 0 +21:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:10/0/physics_layer_0/angular_velocity = 0.0 +22:10/0 = 0 +22:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:10/0/physics_layer_0/angular_velocity = 0.0 +23:10/0 = 0 +23:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:10/0/physics_layer_0/angular_velocity = 0.0 +24:10/0 = 0 +24:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:10/0/physics_layer_0/angular_velocity = 0.0 +25:10/0 = 0 +25:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:10/0/physics_layer_0/angular_velocity = 0.0 +26:10/0 = 0 +26:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:10/0/physics_layer_0/angular_velocity = 0.0 +27:10/0 = 0 +27:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:10/0/physics_layer_0/angular_velocity = 0.0 +28:10/0 = 0 +28:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:10/0/physics_layer_0/angular_velocity = 0.0 +29:10/0 = 0 +29:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:10/0/physics_layer_0/angular_velocity = 0.0 +30:10/0 = 0 +30:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:10/0/physics_layer_0/angular_velocity = 0.0 +31:10/0 = 0 +31:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:10/0/physics_layer_0/angular_velocity = 0.0 +32:10/0 = 0 +32:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:10/0/physics_layer_0/angular_velocity = 0.0 +33:10/0 = 0 +33:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:10/0/physics_layer_0/angular_velocity = 0.0 +34:10/0 = 0 +34:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:10/0/physics_layer_0/angular_velocity = 0.0 +35:10/0 = 0 +35:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:10/0/physics_layer_0/angular_velocity = 0.0 +36:10/0 = 0 +36:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:10/0/physics_layer_0/angular_velocity = 0.0 +37:10/0 = 0 +37:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:10/0/physics_layer_0/angular_velocity = 0.0 +38:10/0 = 0 +38:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:10/0/physics_layer_0/angular_velocity = 0.0 +39:10/0 = 0 +39:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:10/0/physics_layer_0/angular_velocity = 0.0 +40:10/0 = 0 +40:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:10/0/physics_layer_0/angular_velocity = 0.0 +41:10/0 = 0 +41:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:10/0/physics_layer_0/angular_velocity = 0.0 +42:10/0 = 0 +42:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:10/0/physics_layer_0/angular_velocity = 0.0 +43:10/0 = 0 +43:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:10/0/physics_layer_0/angular_velocity = 0.0 +44:10/0 = 0 +44:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:10/0/physics_layer_0/angular_velocity = 0.0 +45:10/0 = 0 +45:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:10/0/physics_layer_0/angular_velocity = 0.0 +46:10/0 = 0 +46:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:10/0/physics_layer_0/angular_velocity = 0.0 +47:10/0 = 0 +47:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:10/0/physics_layer_0/angular_velocity = 0.0 +48:10/0 = 0 +48:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:10/0/physics_layer_0/angular_velocity = 0.0 +0:11/0 = 0 +0:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:11/0/physics_layer_0/angular_velocity = 0.0 +1:11/0 = 0 +1:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:11/0/physics_layer_0/angular_velocity = 0.0 +2:11/0 = 0 +2:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:11/0/physics_layer_0/angular_velocity = 0.0 +3:11/0 = 0 +3:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:11/0/physics_layer_0/angular_velocity = 0.0 +4:11/0 = 0 +4:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:11/0/physics_layer_0/angular_velocity = 0.0 +5:11/0 = 0 +5:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:11/0/physics_layer_0/angular_velocity = 0.0 +6:11/0 = 0 +6:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:11/0/physics_layer_0/angular_velocity = 0.0 +7:11/0 = 0 +7:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:11/0/physics_layer_0/angular_velocity = 0.0 +8:11/0 = 0 +8:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:11/0/physics_layer_0/angular_velocity = 0.0 +9:11/0 = 0 +9:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:11/0/physics_layer_0/angular_velocity = 0.0 +10:11/0 = 0 +10:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:11/0/physics_layer_0/angular_velocity = 0.0 +11:11/0 = 0 +11:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:11/0/physics_layer_0/angular_velocity = 0.0 +12:11/0 = 0 +12:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:11/0/physics_layer_0/angular_velocity = 0.0 +13:11/0 = 0 +13:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:11/0/physics_layer_0/angular_velocity = 0.0 +14:11/0 = 0 +14:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:11/0/physics_layer_0/angular_velocity = 0.0 +15:11/0 = 0 +15:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:11/0/physics_layer_0/angular_velocity = 0.0 +16:11/0 = 0 +16:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:11/0/physics_layer_0/angular_velocity = 0.0 +17:11/0 = 0 +17:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:11/0/physics_layer_0/angular_velocity = 0.0 +18:11/0 = 0 +18:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:11/0/physics_layer_0/angular_velocity = 0.0 +19:11/0 = 0 +19:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:11/0/physics_layer_0/angular_velocity = 0.0 +20:11/0 = 0 +20:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:11/0/physics_layer_0/angular_velocity = 0.0 +21:11/0 = 0 +21:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:11/0/physics_layer_0/angular_velocity = 0.0 +22:11/0 = 0 +22:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:11/0/physics_layer_0/angular_velocity = 0.0 +23:11/0 = 0 +23:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:11/0/physics_layer_0/angular_velocity = 0.0 +24:11/0 = 0 +24:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:11/0/physics_layer_0/angular_velocity = 0.0 +25:11/0 = 0 +25:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:11/0/physics_layer_0/angular_velocity = 0.0 +26:11/0 = 0 +26:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:11/0/physics_layer_0/angular_velocity = 0.0 +27:11/0 = 0 +27:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:11/0/physics_layer_0/angular_velocity = 0.0 +28:11/0 = 0 +28:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:11/0/physics_layer_0/angular_velocity = 0.0 +29:11/0 = 0 +29:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:11/0/physics_layer_0/angular_velocity = 0.0 +30:11/0 = 0 +30:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:11/0/physics_layer_0/angular_velocity = 0.0 +31:11/0 = 0 +31:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:11/0/physics_layer_0/angular_velocity = 0.0 +32:11/0 = 0 +32:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:11/0/physics_layer_0/angular_velocity = 0.0 +33:11/0 = 0 +33:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:11/0/physics_layer_0/angular_velocity = 0.0 +34:11/0 = 0 +34:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:11/0/physics_layer_0/angular_velocity = 0.0 +35:11/0 = 0 +35:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:11/0/physics_layer_0/angular_velocity = 0.0 +36:11/0 = 0 +36:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:11/0/physics_layer_0/angular_velocity = 0.0 +37:11/0 = 0 +37:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:11/0/physics_layer_0/angular_velocity = 0.0 +38:11/0 = 0 +38:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:11/0/physics_layer_0/angular_velocity = 0.0 +39:11/0 = 0 +39:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:11/0/physics_layer_0/angular_velocity = 0.0 +40:11/0 = 0 +40:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:11/0/physics_layer_0/angular_velocity = 0.0 +41:11/0 = 0 +41:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:11/0/physics_layer_0/angular_velocity = 0.0 +42:11/0 = 0 +42:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:11/0/physics_layer_0/angular_velocity = 0.0 +43:11/0 = 0 +43:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:11/0/physics_layer_0/angular_velocity = 0.0 +44:11/0 = 0 +44:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:11/0/physics_layer_0/angular_velocity = 0.0 +45:11/0 = 0 +45:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:11/0/physics_layer_0/angular_velocity = 0.0 +46:11/0 = 0 +46:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:11/0/physics_layer_0/angular_velocity = 0.0 +47:11/0 = 0 +47:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:11/0/physics_layer_0/angular_velocity = 0.0 +48:11/0 = 0 +48:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:11/0/physics_layer_0/angular_velocity = 0.0 +0:12/0 = 0 +0:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:12/0/physics_layer_0/angular_velocity = 0.0 +1:12/0 = 0 +1:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:12/0/physics_layer_0/angular_velocity = 0.0 +2:12/0 = 0 +2:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:12/0/physics_layer_0/angular_velocity = 0.0 +3:12/0 = 0 +3:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:12/0/physics_layer_0/angular_velocity = 0.0 +4:12/0 = 0 +4:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:12/0/physics_layer_0/angular_velocity = 0.0 +5:12/0 = 0 +5:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:12/0/physics_layer_0/angular_velocity = 0.0 +6:12/0 = 0 +6:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:12/0/physics_layer_0/angular_velocity = 0.0 +7:12/0 = 0 +7:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:12/0/physics_layer_0/angular_velocity = 0.0 +8:12/0 = 0 +8:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:12/0/physics_layer_0/angular_velocity = 0.0 +9:12/0 = 0 +9:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:12/0/physics_layer_0/angular_velocity = 0.0 +10:12/0 = 0 +10:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:12/0/physics_layer_0/angular_velocity = 0.0 +11:12/0 = 0 +11:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:12/0/physics_layer_0/angular_velocity = 0.0 +12:12/0 = 0 +12:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:12/0/physics_layer_0/angular_velocity = 0.0 +13:12/0 = 0 +13:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:12/0/physics_layer_0/angular_velocity = 0.0 +14:12/0 = 0 +14:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:12/0/physics_layer_0/angular_velocity = 0.0 +15:12/0 = 0 +15:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:12/0/physics_layer_0/angular_velocity = 0.0 +16:12/0 = 0 +16:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:12/0/physics_layer_0/angular_velocity = 0.0 +17:12/0 = 0 +17:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:12/0/physics_layer_0/angular_velocity = 0.0 +18:12/0 = 0 +18:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:12/0/physics_layer_0/angular_velocity = 0.0 +19:12/0 = 0 +19:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:12/0/physics_layer_0/angular_velocity = 0.0 +20:12/0 = 0 +20:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:12/0/physics_layer_0/angular_velocity = 0.0 +21:12/0 = 0 +21:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:12/0/physics_layer_0/angular_velocity = 0.0 +22:12/0 = 0 +22:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:12/0/physics_layer_0/angular_velocity = 0.0 +23:12/0 = 0 +23:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:12/0/physics_layer_0/angular_velocity = 0.0 +24:12/0 = 0 +24:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:12/0/physics_layer_0/angular_velocity = 0.0 +25:12/0 = 0 +25:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:12/0/physics_layer_0/angular_velocity = 0.0 +26:12/0 = 0 +26:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:12/0/physics_layer_0/angular_velocity = 0.0 +27:12/0 = 0 +27:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:12/0/physics_layer_0/angular_velocity = 0.0 +28:12/0 = 0 +28:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:12/0/physics_layer_0/angular_velocity = 0.0 +29:12/0 = 0 +29:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:12/0/physics_layer_0/angular_velocity = 0.0 +30:12/0 = 0 +30:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:12/0/physics_layer_0/angular_velocity = 0.0 +31:12/0 = 0 +31:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:12/0/physics_layer_0/angular_velocity = 0.0 +32:12/0 = 0 +32:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:12/0/physics_layer_0/angular_velocity = 0.0 +33:12/0 = 0 +33:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:12/0/physics_layer_0/angular_velocity = 0.0 +34:12/0 = 0 +34:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:12/0/physics_layer_0/angular_velocity = 0.0 +35:12/0 = 0 +35:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:12/0/physics_layer_0/angular_velocity = 0.0 +36:12/0 = 0 +36:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:12/0/physics_layer_0/angular_velocity = 0.0 +37:12/0 = 0 +37:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:12/0/physics_layer_0/angular_velocity = 0.0 +38:12/0 = 0 +38:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:12/0/physics_layer_0/angular_velocity = 0.0 +39:12/0 = 0 +39:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:12/0/physics_layer_0/angular_velocity = 0.0 +40:12/0 = 0 +40:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:12/0/physics_layer_0/angular_velocity = 0.0 +41:12/0 = 0 +41:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:12/0/physics_layer_0/angular_velocity = 0.0 +42:12/0 = 0 +42:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:12/0/physics_layer_0/angular_velocity = 0.0 +43:12/0 = 0 +43:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:12/0/physics_layer_0/angular_velocity = 0.0 +44:12/0 = 0 +44:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:12/0/physics_layer_0/angular_velocity = 0.0 +45:12/0 = 0 +45:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:12/0/physics_layer_0/angular_velocity = 0.0 +46:12/0 = 0 +46:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:12/0/physics_layer_0/angular_velocity = 0.0 +47:12/0 = 0 +47:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:12/0/physics_layer_0/angular_velocity = 0.0 +48:12/0 = 0 +48:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:12/0/physics_layer_0/angular_velocity = 0.0 +0:13/0 = 0 +0:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:13/0/physics_layer_0/angular_velocity = 0.0 +1:13/0 = 0 +1:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:13/0/physics_layer_0/angular_velocity = 0.0 +2:13/0 = 0 +2:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:13/0/physics_layer_0/angular_velocity = 0.0 +3:13/0 = 0 +3:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:13/0/physics_layer_0/angular_velocity = 0.0 +4:13/0 = 0 +4:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:13/0/physics_layer_0/angular_velocity = 0.0 +5:13/0 = 0 +5:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:13/0/physics_layer_0/angular_velocity = 0.0 +6:13/0 = 0 +6:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:13/0/physics_layer_0/angular_velocity = 0.0 +7:13/0 = 0 +7:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:13/0/physics_layer_0/angular_velocity = 0.0 +8:13/0 = 0 +8:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:13/0/physics_layer_0/angular_velocity = 0.0 +9:13/0 = 0 +9:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:13/0/physics_layer_0/angular_velocity = 0.0 +10:13/0 = 0 +10:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:13/0/physics_layer_0/angular_velocity = 0.0 +11:13/0 = 0 +11:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:13/0/physics_layer_0/angular_velocity = 0.0 +12:13/0 = 0 +12:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:13/0/physics_layer_0/angular_velocity = 0.0 +13:13/0 = 0 +13:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:13/0/physics_layer_0/angular_velocity = 0.0 +14:13/0 = 0 +14:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:13/0/physics_layer_0/angular_velocity = 0.0 +15:13/0 = 0 +15:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:13/0/physics_layer_0/angular_velocity = 0.0 +16:13/0 = 0 +16:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:13/0/physics_layer_0/angular_velocity = 0.0 +17:13/0 = 0 +17:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:13/0/physics_layer_0/angular_velocity = 0.0 +18:13/0 = 0 +18:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:13/0/physics_layer_0/angular_velocity = 0.0 +19:13/0 = 0 +19:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:13/0/physics_layer_0/angular_velocity = 0.0 +20:13/0 = 0 +20:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:13/0/physics_layer_0/angular_velocity = 0.0 +21:13/0 = 0 +21:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:13/0/physics_layer_0/angular_velocity = 0.0 +22:13/0 = 0 +22:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:13/0/physics_layer_0/angular_velocity = 0.0 +23:13/0 = 0 +23:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:13/0/physics_layer_0/angular_velocity = 0.0 +24:13/0 = 0 +24:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:13/0/physics_layer_0/angular_velocity = 0.0 +25:13/0 = 0 +25:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:13/0/physics_layer_0/angular_velocity = 0.0 +26:13/0 = 0 +26:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:13/0/physics_layer_0/angular_velocity = 0.0 +27:13/0 = 0 +27:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:13/0/physics_layer_0/angular_velocity = 0.0 +28:13/0 = 0 +28:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:13/0/physics_layer_0/angular_velocity = 0.0 +29:13/0 = 0 +29:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:13/0/physics_layer_0/angular_velocity = 0.0 +30:13/0 = 0 +30:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:13/0/physics_layer_0/angular_velocity = 0.0 +31:13/0 = 0 +31:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:13/0/physics_layer_0/angular_velocity = 0.0 +32:13/0 = 0 +32:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:13/0/physics_layer_0/angular_velocity = 0.0 +33:13/0 = 0 +33:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:13/0/physics_layer_0/angular_velocity = 0.0 +34:13/0 = 0 +34:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:13/0/physics_layer_0/angular_velocity = 0.0 +35:13/0 = 0 +35:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:13/0/physics_layer_0/angular_velocity = 0.0 +36:13/0 = 0 +36:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:13/0/physics_layer_0/angular_velocity = 0.0 +37:13/0 = 0 +37:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:13/0/physics_layer_0/angular_velocity = 0.0 +38:13/0 = 0 +38:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:13/0/physics_layer_0/angular_velocity = 0.0 +39:13/0 = 0 +39:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:13/0/physics_layer_0/angular_velocity = 0.0 +40:13/0 = 0 +40:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:13/0/physics_layer_0/angular_velocity = 0.0 +41:13/0 = 0 +41:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:13/0/physics_layer_0/angular_velocity = 0.0 +42:13/0 = 0 +42:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:13/0/physics_layer_0/angular_velocity = 0.0 +43:13/0 = 0 +43:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:13/0/physics_layer_0/angular_velocity = 0.0 +44:13/0 = 0 +44:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:13/0/physics_layer_0/angular_velocity = 0.0 +45:13/0 = 0 +45:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:13/0/physics_layer_0/angular_velocity = 0.0 +46:13/0 = 0 +46:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:13/0/physics_layer_0/angular_velocity = 0.0 +47:13/0 = 0 +47:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:13/0/physics_layer_0/angular_velocity = 0.0 +48:13/0 = 0 +48:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:13/0/physics_layer_0/angular_velocity = 0.0 +0:14/0 = 0 +0:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:14/0/physics_layer_0/angular_velocity = 0.0 +1:14/0 = 0 +1:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:14/0/physics_layer_0/angular_velocity = 0.0 +2:14/0 = 0 +2:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:14/0/physics_layer_0/angular_velocity = 0.0 +3:14/0 = 0 +3:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:14/0/physics_layer_0/angular_velocity = 0.0 +4:14/0 = 0 +4:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:14/0/physics_layer_0/angular_velocity = 0.0 +5:14/0 = 0 +5:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:14/0/physics_layer_0/angular_velocity = 0.0 +6:14/0 = 0 +6:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:14/0/physics_layer_0/angular_velocity = 0.0 +7:14/0 = 0 +7:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:14/0/physics_layer_0/angular_velocity = 0.0 +8:14/0 = 0 +8:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:14/0/physics_layer_0/angular_velocity = 0.0 +9:14/0 = 0 +9:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:14/0/physics_layer_0/angular_velocity = 0.0 +10:14/0 = 0 +10:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:14/0/physics_layer_0/angular_velocity = 0.0 +11:14/0 = 0 +11:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:14/0/physics_layer_0/angular_velocity = 0.0 +12:14/0 = 0 +12:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:14/0/physics_layer_0/angular_velocity = 0.0 +13:14/0 = 0 +13:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:14/0/physics_layer_0/angular_velocity = 0.0 +14:14/0 = 0 +14:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:14/0/physics_layer_0/angular_velocity = 0.0 +15:14/0 = 0 +15:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:14/0/physics_layer_0/angular_velocity = 0.0 +16:14/0 = 0 +16:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:14/0/physics_layer_0/angular_velocity = 0.0 +17:14/0 = 0 +17:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:14/0/physics_layer_0/angular_velocity = 0.0 +18:14/0 = 0 +18:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:14/0/physics_layer_0/angular_velocity = 0.0 +19:14/0 = 0 +19:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:14/0/physics_layer_0/angular_velocity = 0.0 +20:14/0 = 0 +20:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:14/0/physics_layer_0/angular_velocity = 0.0 +21:14/0 = 0 +21:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:14/0/physics_layer_0/angular_velocity = 0.0 +22:14/0 = 0 +22:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:14/0/physics_layer_0/angular_velocity = 0.0 +23:14/0 = 0 +23:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:14/0/physics_layer_0/angular_velocity = 0.0 +24:14/0 = 0 +24:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:14/0/physics_layer_0/angular_velocity = 0.0 +25:14/0 = 0 +25:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:14/0/physics_layer_0/angular_velocity = 0.0 +26:14/0 = 0 +26:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:14/0/physics_layer_0/angular_velocity = 0.0 +27:14/0 = 0 +27:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:14/0/physics_layer_0/angular_velocity = 0.0 +28:14/0 = 0 +28:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:14/0/physics_layer_0/angular_velocity = 0.0 +29:14/0 = 0 +29:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:14/0/physics_layer_0/angular_velocity = 0.0 +30:14/0 = 0 +30:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:14/0/physics_layer_0/angular_velocity = 0.0 +31:14/0 = 0 +31:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:14/0/physics_layer_0/angular_velocity = 0.0 +32:14/0 = 0 +32:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:14/0/physics_layer_0/angular_velocity = 0.0 +33:14/0 = 0 +33:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:14/0/physics_layer_0/angular_velocity = 0.0 +34:14/0 = 0 +34:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:14/0/physics_layer_0/angular_velocity = 0.0 +35:14/0 = 0 +35:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:14/0/physics_layer_0/angular_velocity = 0.0 +36:14/0 = 0 +36:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:14/0/physics_layer_0/angular_velocity = 0.0 +37:14/0 = 0 +37:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:14/0/physics_layer_0/angular_velocity = 0.0 +38:14/0 = 0 +38:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:14/0/physics_layer_0/angular_velocity = 0.0 +39:14/0 = 0 +39:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:14/0/physics_layer_0/angular_velocity = 0.0 +40:14/0 = 0 +40:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:14/0/physics_layer_0/angular_velocity = 0.0 +41:14/0 = 0 +41:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:14/0/physics_layer_0/angular_velocity = 0.0 +42:14/0 = 0 +42:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:14/0/physics_layer_0/angular_velocity = 0.0 +43:14/0 = 0 +43:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:14/0/physics_layer_0/angular_velocity = 0.0 +44:14/0 = 0 +44:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:14/0/physics_layer_0/angular_velocity = 0.0 +45:14/0 = 0 +45:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:14/0/physics_layer_0/angular_velocity = 0.0 +46:14/0 = 0 +46:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:14/0/physics_layer_0/angular_velocity = 0.0 +47:14/0 = 0 +47:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:14/0/physics_layer_0/angular_velocity = 0.0 +48:14/0 = 0 +48:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:14/0/physics_layer_0/angular_velocity = 0.0 +0:15/0 = 0 +0:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:15/0/physics_layer_0/angular_velocity = 0.0 +1:15/0 = 0 +1:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:15/0/physics_layer_0/angular_velocity = 0.0 +2:15/0 = 0 +2:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:15/0/physics_layer_0/angular_velocity = 0.0 +3:15/0 = 0 +3:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:15/0/physics_layer_0/angular_velocity = 0.0 +4:15/0 = 0 +4:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:15/0/physics_layer_0/angular_velocity = 0.0 +5:15/0 = 0 +5:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:15/0/physics_layer_0/angular_velocity = 0.0 +6:15/0 = 0 +6:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:15/0/physics_layer_0/angular_velocity = 0.0 +7:15/0 = 0 +7:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:15/0/physics_layer_0/angular_velocity = 0.0 +8:15/0 = 0 +8:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:15/0/physics_layer_0/angular_velocity = 0.0 +9:15/0 = 0 +9:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:15/0/physics_layer_0/angular_velocity = 0.0 +10:15/0 = 0 +10:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:15/0/physics_layer_0/angular_velocity = 0.0 +11:15/0 = 0 +11:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:15/0/physics_layer_0/angular_velocity = 0.0 +12:15/0 = 0 +12:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:15/0/physics_layer_0/angular_velocity = 0.0 +13:15/0 = 0 +13:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:15/0/physics_layer_0/angular_velocity = 0.0 +14:15/0 = 0 +14:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:15/0/physics_layer_0/angular_velocity = 0.0 +15:15/0 = 0 +15:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:15/0/physics_layer_0/angular_velocity = 0.0 +16:15/0 = 0 +16:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:15/0/physics_layer_0/angular_velocity = 0.0 +17:15/0 = 0 +17:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:15/0/physics_layer_0/angular_velocity = 0.0 +18:15/0 = 0 +18:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:15/0/physics_layer_0/angular_velocity = 0.0 +19:15/0 = 0 +19:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:15/0/physics_layer_0/angular_velocity = 0.0 +20:15/0 = 0 +20:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:15/0/physics_layer_0/angular_velocity = 0.0 +21:15/0 = 0 +21:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:15/0/physics_layer_0/angular_velocity = 0.0 +22:15/0 = 0 +22:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:15/0/physics_layer_0/angular_velocity = 0.0 +23:15/0 = 0 +23:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:15/0/physics_layer_0/angular_velocity = 0.0 +24:15/0 = 0 +24:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:15/0/physics_layer_0/angular_velocity = 0.0 +25:15/0 = 0 +25:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:15/0/physics_layer_0/angular_velocity = 0.0 +26:15/0 = 0 +26:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:15/0/physics_layer_0/angular_velocity = 0.0 +27:15/0 = 0 +27:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:15/0/physics_layer_0/angular_velocity = 0.0 +28:15/0 = 0 +28:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:15/0/physics_layer_0/angular_velocity = 0.0 +29:15/0 = 0 +29:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:15/0/physics_layer_0/angular_velocity = 0.0 +30:15/0 = 0 +30:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:15/0/physics_layer_0/angular_velocity = 0.0 +31:15/0 = 0 +31:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:15/0/physics_layer_0/angular_velocity = 0.0 +32:15/0 = 0 +32:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:15/0/physics_layer_0/angular_velocity = 0.0 +33:15/0 = 0 +33:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:15/0/physics_layer_0/angular_velocity = 0.0 +34:15/0 = 0 +34:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:15/0/physics_layer_0/angular_velocity = 0.0 +35:15/0 = 0 +35:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:15/0/physics_layer_0/angular_velocity = 0.0 +36:15/0 = 0 +36:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:15/0/physics_layer_0/angular_velocity = 0.0 +37:15/0 = 0 +37:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:15/0/physics_layer_0/angular_velocity = 0.0 +38:15/0 = 0 +38:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:15/0/physics_layer_0/angular_velocity = 0.0 +39:15/0 = 0 +39:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:15/0/physics_layer_0/angular_velocity = 0.0 +40:15/0 = 0 +40:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:15/0/physics_layer_0/angular_velocity = 0.0 +41:15/0 = 0 +41:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:15/0/physics_layer_0/angular_velocity = 0.0 +42:15/0 = 0 +42:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:15/0/physics_layer_0/angular_velocity = 0.0 +43:15/0 = 0 +43:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:15/0/physics_layer_0/angular_velocity = 0.0 +44:15/0 = 0 +44:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:15/0/physics_layer_0/angular_velocity = 0.0 +45:15/0 = 0 +45:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:15/0/physics_layer_0/angular_velocity = 0.0 +46:15/0 = 0 +46:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:15/0/physics_layer_0/angular_velocity = 0.0 +47:15/0 = 0 +47:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:15/0/physics_layer_0/angular_velocity = 0.0 +48:15/0 = 0 +48:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:15/0/physics_layer_0/angular_velocity = 0.0 +0:16/0 = 0 +0:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:16/0/physics_layer_0/angular_velocity = 0.0 +1:16/0 = 0 +1:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:16/0/physics_layer_0/angular_velocity = 0.0 +2:16/0 = 0 +2:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:16/0/physics_layer_0/angular_velocity = 0.0 +3:16/0 = 0 +3:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:16/0/physics_layer_0/angular_velocity = 0.0 +4:16/0 = 0 +4:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:16/0/physics_layer_0/angular_velocity = 0.0 +5:16/0 = 0 +5:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:16/0/physics_layer_0/angular_velocity = 0.0 +6:16/0 = 0 +6:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:16/0/physics_layer_0/angular_velocity = 0.0 +7:16/0 = 0 +7:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:16/0/physics_layer_0/angular_velocity = 0.0 +8:16/0 = 0 +8:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:16/0/physics_layer_0/angular_velocity = 0.0 +9:16/0 = 0 +9:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:16/0/physics_layer_0/angular_velocity = 0.0 +10:16/0 = 0 +10:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:16/0/physics_layer_0/angular_velocity = 0.0 +11:16/0 = 0 +11:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:16/0/physics_layer_0/angular_velocity = 0.0 +12:16/0 = 0 +12:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:16/0/physics_layer_0/angular_velocity = 0.0 +13:16/0 = 0 +13:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:16/0/physics_layer_0/angular_velocity = 0.0 +14:16/0 = 0 +14:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:16/0/physics_layer_0/angular_velocity = 0.0 +15:16/0 = 0 +15:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:16/0/physics_layer_0/angular_velocity = 0.0 +16:16/0 = 0 +16:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:16/0/physics_layer_0/angular_velocity = 0.0 +17:16/0 = 0 +17:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:16/0/physics_layer_0/angular_velocity = 0.0 +18:16/0 = 0 +18:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:16/0/physics_layer_0/angular_velocity = 0.0 +19:16/0 = 0 +19:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:16/0/physics_layer_0/angular_velocity = 0.0 +20:16/0 = 0 +20:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:16/0/physics_layer_0/angular_velocity = 0.0 +21:16/0 = 0 +21:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:16/0/physics_layer_0/angular_velocity = 0.0 +22:16/0 = 0 +22:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:16/0/physics_layer_0/angular_velocity = 0.0 +23:16/0 = 0 +23:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:16/0/physics_layer_0/angular_velocity = 0.0 +24:16/0 = 0 +24:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:16/0/physics_layer_0/angular_velocity = 0.0 +25:16/0 = 0 +25:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:16/0/physics_layer_0/angular_velocity = 0.0 +26:16/0 = 0 +26:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:16/0/physics_layer_0/angular_velocity = 0.0 +27:16/0 = 0 +27:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:16/0/physics_layer_0/angular_velocity = 0.0 +28:16/0 = 0 +28:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:16/0/physics_layer_0/angular_velocity = 0.0 +29:16/0 = 0 +29:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:16/0/physics_layer_0/angular_velocity = 0.0 +30:16/0 = 0 +30:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:16/0/physics_layer_0/angular_velocity = 0.0 +31:16/0 = 0 +31:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:16/0/physics_layer_0/angular_velocity = 0.0 +32:16/0 = 0 +32:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:16/0/physics_layer_0/angular_velocity = 0.0 +33:16/0 = 0 +33:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:16/0/physics_layer_0/angular_velocity = 0.0 +34:16/0 = 0 +34:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:16/0/physics_layer_0/angular_velocity = 0.0 +35:16/0 = 0 +35:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:16/0/physics_layer_0/angular_velocity = 0.0 +36:16/0 = 0 +36:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:16/0/physics_layer_0/angular_velocity = 0.0 +37:16/0 = 0 +37:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:16/0/physics_layer_0/angular_velocity = 0.0 +38:16/0 = 0 +38:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:16/0/physics_layer_0/angular_velocity = 0.0 +39:16/0 = 0 +39:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:16/0/physics_layer_0/angular_velocity = 0.0 +40:16/0 = 0 +40:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:16/0/physics_layer_0/angular_velocity = 0.0 +41:16/0 = 0 +41:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:16/0/physics_layer_0/angular_velocity = 0.0 +42:16/0 = 0 +42:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:16/0/physics_layer_0/angular_velocity = 0.0 +43:16/0 = 0 +43:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:16/0/physics_layer_0/angular_velocity = 0.0 +44:16/0 = 0 +44:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:16/0/physics_layer_0/angular_velocity = 0.0 +45:16/0 = 0 +45:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:16/0/physics_layer_0/angular_velocity = 0.0 +46:16/0 = 0 +46:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:16/0/physics_layer_0/angular_velocity = 0.0 +47:16/0 = 0 +47:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:16/0/physics_layer_0/angular_velocity = 0.0 +48:16/0 = 0 +48:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:16/0/physics_layer_0/angular_velocity = 0.0 +0:17/0 = 0 +0:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:17/0/physics_layer_0/angular_velocity = 0.0 +1:17/0 = 0 +1:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:17/0/physics_layer_0/angular_velocity = 0.0 +2:17/0 = 0 +2:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:17/0/physics_layer_0/angular_velocity = 0.0 +3:17/0 = 0 +3:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:17/0/physics_layer_0/angular_velocity = 0.0 +4:17/0 = 0 +4:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:17/0/physics_layer_0/angular_velocity = 0.0 +5:17/0 = 0 +5:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:17/0/physics_layer_0/angular_velocity = 0.0 +6:17/0 = 0 +6:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:17/0/physics_layer_0/angular_velocity = 0.0 +7:17/0 = 0 +7:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:17/0/physics_layer_0/angular_velocity = 0.0 +8:17/0 = 0 +8:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:17/0/physics_layer_0/angular_velocity = 0.0 +9:17/0 = 0 +9:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:17/0/physics_layer_0/angular_velocity = 0.0 +10:17/0 = 0 +10:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:17/0/physics_layer_0/angular_velocity = 0.0 +11:17/0 = 0 +11:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:17/0/physics_layer_0/angular_velocity = 0.0 +12:17/0 = 0 +12:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:17/0/physics_layer_0/angular_velocity = 0.0 +13:17/0 = 0 +13:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:17/0/physics_layer_0/angular_velocity = 0.0 +14:17/0 = 0 +14:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:17/0/physics_layer_0/angular_velocity = 0.0 +15:17/0 = 0 +15:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:17/0/physics_layer_0/angular_velocity = 0.0 +16:17/0 = 0 +16:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:17/0/physics_layer_0/angular_velocity = 0.0 +17:17/0 = 0 +17:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:17/0/physics_layer_0/angular_velocity = 0.0 +18:17/0 = 0 +18:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:17/0/physics_layer_0/angular_velocity = 0.0 +19:17/0 = 0 +19:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:17/0/physics_layer_0/angular_velocity = 0.0 +20:17/0 = 0 +20:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:17/0/physics_layer_0/angular_velocity = 0.0 +21:17/0 = 0 +21:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:17/0/physics_layer_0/angular_velocity = 0.0 +22:17/0 = 0 +22:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:17/0/physics_layer_0/angular_velocity = 0.0 +23:17/0 = 0 +23:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:17/0/physics_layer_0/angular_velocity = 0.0 +24:17/0 = 0 +24:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:17/0/physics_layer_0/angular_velocity = 0.0 +25:17/0 = 0 +25:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:17/0/physics_layer_0/angular_velocity = 0.0 +26:17/0 = 0 +26:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:17/0/physics_layer_0/angular_velocity = 0.0 +27:17/0 = 0 +27:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:17/0/physics_layer_0/angular_velocity = 0.0 +28:17/0 = 0 +28:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:17/0/physics_layer_0/angular_velocity = 0.0 +29:17/0 = 0 +29:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:17/0/physics_layer_0/angular_velocity = 0.0 +30:17/0 = 0 +30:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:17/0/physics_layer_0/angular_velocity = 0.0 +31:17/0 = 0 +31:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:17/0/physics_layer_0/angular_velocity = 0.0 +32:17/0 = 0 +32:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:17/0/physics_layer_0/angular_velocity = 0.0 +33:17/0 = 0 +33:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:17/0/physics_layer_0/angular_velocity = 0.0 +34:17/0 = 0 +34:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:17/0/physics_layer_0/angular_velocity = 0.0 +35:17/0 = 0 +35:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:17/0/physics_layer_0/angular_velocity = 0.0 +36:17/0 = 0 +36:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:17/0/physics_layer_0/angular_velocity = 0.0 +37:17/0 = 0 +37:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:17/0/physics_layer_0/angular_velocity = 0.0 +38:17/0 = 0 +38:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:17/0/physics_layer_0/angular_velocity = 0.0 +39:17/0 = 0 +39:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:17/0/physics_layer_0/angular_velocity = 0.0 +40:17/0 = 0 +40:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:17/0/physics_layer_0/angular_velocity = 0.0 +41:17/0 = 0 +41:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:17/0/physics_layer_0/angular_velocity = 0.0 +42:17/0 = 0 +42:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:17/0/physics_layer_0/angular_velocity = 0.0 +43:17/0 = 0 +43:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:17/0/physics_layer_0/angular_velocity = 0.0 +44:17/0 = 0 +44:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:17/0/physics_layer_0/angular_velocity = 0.0 +45:17/0 = 0 +45:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:17/0/physics_layer_0/angular_velocity = 0.0 +46:17/0 = 0 +46:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:17/0/physics_layer_0/angular_velocity = 0.0 +47:17/0 = 0 +47:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:17/0/physics_layer_0/angular_velocity = 0.0 +48:17/0 = 0 +48:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:17/0/physics_layer_0/angular_velocity = 0.0 +0:18/0 = 0 +0:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:18/0/physics_layer_0/angular_velocity = 0.0 +1:18/0 = 0 +1:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:18/0/physics_layer_0/angular_velocity = 0.0 +2:18/0 = 0 +2:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:18/0/physics_layer_0/angular_velocity = 0.0 +3:18/0 = 0 +3:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:18/0/physics_layer_0/angular_velocity = 0.0 +4:18/0 = 0 +4:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:18/0/physics_layer_0/angular_velocity = 0.0 +5:18/0 = 0 +5:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:18/0/physics_layer_0/angular_velocity = 0.0 +6:18/0 = 0 +6:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:18/0/physics_layer_0/angular_velocity = 0.0 +7:18/0 = 0 +7:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:18/0/physics_layer_0/angular_velocity = 0.0 +8:18/0 = 0 +8:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:18/0/physics_layer_0/angular_velocity = 0.0 +9:18/0 = 0 +9:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:18/0/physics_layer_0/angular_velocity = 0.0 +10:18/0 = 0 +10:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:18/0/physics_layer_0/angular_velocity = 0.0 +11:18/0 = 0 +11:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:18/0/physics_layer_0/angular_velocity = 0.0 +12:18/0 = 0 +12:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:18/0/physics_layer_0/angular_velocity = 0.0 +13:18/0 = 0 +13:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:18/0/physics_layer_0/angular_velocity = 0.0 +14:18/0 = 0 +14:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:18/0/physics_layer_0/angular_velocity = 0.0 +15:18/0 = 0 +15:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:18/0/physics_layer_0/angular_velocity = 0.0 +16:18/0 = 0 +16:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:18/0/physics_layer_0/angular_velocity = 0.0 +17:18/0 = 0 +17:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:18/0/physics_layer_0/angular_velocity = 0.0 +18:18/0 = 0 +18:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:18/0/physics_layer_0/angular_velocity = 0.0 +19:18/0 = 0 +19:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:18/0/physics_layer_0/angular_velocity = 0.0 +20:18/0 = 0 +20:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:18/0/physics_layer_0/angular_velocity = 0.0 +21:18/0 = 0 +21:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:18/0/physics_layer_0/angular_velocity = 0.0 +22:18/0 = 0 +22:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:18/0/physics_layer_0/angular_velocity = 0.0 +23:18/0 = 0 +23:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:18/0/physics_layer_0/angular_velocity = 0.0 +24:18/0 = 0 +24:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:18/0/physics_layer_0/angular_velocity = 0.0 +25:18/0 = 0 +25:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:18/0/physics_layer_0/angular_velocity = 0.0 +26:18/0 = 0 +26:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:18/0/physics_layer_0/angular_velocity = 0.0 +27:18/0 = 0 +27:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:18/0/physics_layer_0/angular_velocity = 0.0 +28:18/0 = 0 +28:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:18/0/physics_layer_0/angular_velocity = 0.0 +29:18/0 = 0 +29:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:18/0/physics_layer_0/angular_velocity = 0.0 +30:18/0 = 0 +30:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:18/0/physics_layer_0/angular_velocity = 0.0 +31:18/0 = 0 +31:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:18/0/physics_layer_0/angular_velocity = 0.0 +32:18/0 = 0 +32:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:18/0/physics_layer_0/angular_velocity = 0.0 +33:18/0 = 0 +33:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:18/0/physics_layer_0/angular_velocity = 0.0 +34:18/0 = 0 +34:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:18/0/physics_layer_0/angular_velocity = 0.0 +35:18/0 = 0 +35:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:18/0/physics_layer_0/angular_velocity = 0.0 +36:18/0 = 0 +36:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:18/0/physics_layer_0/angular_velocity = 0.0 +37:18/0 = 0 +37:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:18/0/physics_layer_0/angular_velocity = 0.0 +38:18/0 = 0 +38:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:18/0/physics_layer_0/angular_velocity = 0.0 +39:18/0 = 0 +39:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:18/0/physics_layer_0/angular_velocity = 0.0 +40:18/0 = 0 +40:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:18/0/physics_layer_0/angular_velocity = 0.0 +41:18/0 = 0 +41:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:18/0/physics_layer_0/angular_velocity = 0.0 +42:18/0 = 0 +42:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:18/0/physics_layer_0/angular_velocity = 0.0 +43:18/0 = 0 +43:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:18/0/physics_layer_0/angular_velocity = 0.0 +44:18/0 = 0 +44:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:18/0/physics_layer_0/angular_velocity = 0.0 +45:18/0 = 0 +45:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:18/0/physics_layer_0/angular_velocity = 0.0 +46:18/0 = 0 +46:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:18/0/physics_layer_0/angular_velocity = 0.0 +47:18/0 = 0 +47:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:18/0/physics_layer_0/angular_velocity = 0.0 +48:18/0 = 0 +48:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:18/0/physics_layer_0/angular_velocity = 0.0 +0:19/0 = 0 +0:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:19/0/physics_layer_0/angular_velocity = 0.0 +1:19/0 = 0 +1:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:19/0/physics_layer_0/angular_velocity = 0.0 +2:19/0 = 0 +2:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:19/0/physics_layer_0/angular_velocity = 0.0 +3:19/0 = 0 +3:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:19/0/physics_layer_0/angular_velocity = 0.0 +4:19/0 = 0 +4:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:19/0/physics_layer_0/angular_velocity = 0.0 +5:19/0 = 0 +5:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:19/0/physics_layer_0/angular_velocity = 0.0 +6:19/0 = 0 +6:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:19/0/physics_layer_0/angular_velocity = 0.0 +7:19/0 = 0 +7:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:19/0/physics_layer_0/angular_velocity = 0.0 +8:19/0 = 0 +8:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:19/0/physics_layer_0/angular_velocity = 0.0 +9:19/0 = 0 +9:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:19/0/physics_layer_0/angular_velocity = 0.0 +10:19/0 = 0 +10:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:19/0/physics_layer_0/angular_velocity = 0.0 +11:19/0 = 0 +11:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:19/0/physics_layer_0/angular_velocity = 0.0 +12:19/0 = 0 +12:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:19/0/physics_layer_0/angular_velocity = 0.0 +13:19/0 = 0 +13:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:19/0/physics_layer_0/angular_velocity = 0.0 +14:19/0 = 0 +14:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:19/0/physics_layer_0/angular_velocity = 0.0 +15:19/0 = 0 +15:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:19/0/physics_layer_0/angular_velocity = 0.0 +16:19/0 = 0 +16:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:19/0/physics_layer_0/angular_velocity = 0.0 +17:19/0 = 0 +17:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:19/0/physics_layer_0/angular_velocity = 0.0 +18:19/0 = 0 +18:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:19/0/physics_layer_0/angular_velocity = 0.0 +19:19/0 = 0 +19:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:19/0/physics_layer_0/angular_velocity = 0.0 +20:19/0 = 0 +20:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:19/0/physics_layer_0/angular_velocity = 0.0 +21:19/0 = 0 +21:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:19/0/physics_layer_0/angular_velocity = 0.0 +22:19/0 = 0 +22:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:19/0/physics_layer_0/angular_velocity = 0.0 +23:19/0 = 0 +23:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:19/0/physics_layer_0/angular_velocity = 0.0 +24:19/0 = 0 +24:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:19/0/physics_layer_0/angular_velocity = 0.0 +25:19/0 = 0 +25:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:19/0/physics_layer_0/angular_velocity = 0.0 +26:19/0 = 0 +26:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:19/0/physics_layer_0/angular_velocity = 0.0 +27:19/0 = 0 +27:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:19/0/physics_layer_0/angular_velocity = 0.0 +28:19/0 = 0 +28:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:19/0/physics_layer_0/angular_velocity = 0.0 +29:19/0 = 0 +29:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:19/0/physics_layer_0/angular_velocity = 0.0 +30:19/0 = 0 +30:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:19/0/physics_layer_0/angular_velocity = 0.0 +31:19/0 = 0 +31:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:19/0/physics_layer_0/angular_velocity = 0.0 +32:19/0 = 0 +32:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:19/0/physics_layer_0/angular_velocity = 0.0 +33:19/0 = 0 +33:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:19/0/physics_layer_0/angular_velocity = 0.0 +34:19/0 = 0 +34:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:19/0/physics_layer_0/angular_velocity = 0.0 +35:19/0 = 0 +35:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:19/0/physics_layer_0/angular_velocity = 0.0 +36:19/0 = 0 +36:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:19/0/physics_layer_0/angular_velocity = 0.0 +37:19/0 = 0 +37:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:19/0/physics_layer_0/angular_velocity = 0.0 +38:19/0 = 0 +38:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:19/0/physics_layer_0/angular_velocity = 0.0 +39:19/0 = 0 +39:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:19/0/physics_layer_0/angular_velocity = 0.0 +40:19/0 = 0 +40:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:19/0/physics_layer_0/angular_velocity = 0.0 +41:19/0 = 0 +41:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:19/0/physics_layer_0/angular_velocity = 0.0 +42:19/0 = 0 +42:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:19/0/physics_layer_0/angular_velocity = 0.0 +43:19/0 = 0 +43:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:19/0/physics_layer_0/angular_velocity = 0.0 +44:19/0 = 0 +44:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:19/0/physics_layer_0/angular_velocity = 0.0 +45:19/0 = 0 +45:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:19/0/physics_layer_0/angular_velocity = 0.0 +46:19/0 = 0 +46:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:19/0/physics_layer_0/angular_velocity = 0.0 +47:19/0 = 0 +47:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:19/0/physics_layer_0/angular_velocity = 0.0 +48:19/0 = 0 +48:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:19/0/physics_layer_0/angular_velocity = 0.0 +0:20/0 = 0 +0:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:20/0/physics_layer_0/angular_velocity = 0.0 +1:20/0 = 0 +1:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:20/0/physics_layer_0/angular_velocity = 0.0 +2:20/0 = 0 +2:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:20/0/physics_layer_0/angular_velocity = 0.0 +3:20/0 = 0 +3:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:20/0/physics_layer_0/angular_velocity = 0.0 +4:20/0 = 0 +4:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:20/0/physics_layer_0/angular_velocity = 0.0 +5:20/0 = 0 +5:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:20/0/physics_layer_0/angular_velocity = 0.0 +6:20/0 = 0 +6:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:20/0/physics_layer_0/angular_velocity = 0.0 +7:20/0 = 0 +7:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:20/0/physics_layer_0/angular_velocity = 0.0 +8:20/0 = 0 +8:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:20/0/physics_layer_0/angular_velocity = 0.0 +9:20/0 = 0 +9:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:20/0/physics_layer_0/angular_velocity = 0.0 +10:20/0 = 0 +10:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:20/0/physics_layer_0/angular_velocity = 0.0 +11:20/0 = 0 +11:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:20/0/physics_layer_0/angular_velocity = 0.0 +12:20/0 = 0 +12:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:20/0/physics_layer_0/angular_velocity = 0.0 +13:20/0 = 0 +13:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:20/0/physics_layer_0/angular_velocity = 0.0 +14:20/0 = 0 +14:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:20/0/physics_layer_0/angular_velocity = 0.0 +15:20/0 = 0 +15:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:20/0/physics_layer_0/angular_velocity = 0.0 +16:20/0 = 0 +16:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:20/0/physics_layer_0/angular_velocity = 0.0 +17:20/0 = 0 +17:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:20/0/physics_layer_0/angular_velocity = 0.0 +18:20/0 = 0 +18:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:20/0/physics_layer_0/angular_velocity = 0.0 +19:20/0 = 0 +19:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:20/0/physics_layer_0/angular_velocity = 0.0 +20:20/0 = 0 +20:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:20/0/physics_layer_0/angular_velocity = 0.0 +21:20/0 = 0 +21:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:20/0/physics_layer_0/angular_velocity = 0.0 +22:20/0 = 0 +22:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:20/0/physics_layer_0/angular_velocity = 0.0 +23:20/0 = 0 +23:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:20/0/physics_layer_0/angular_velocity = 0.0 +24:20/0 = 0 +24:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:20/0/physics_layer_0/angular_velocity = 0.0 +25:20/0 = 0 +25:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:20/0/physics_layer_0/angular_velocity = 0.0 +26:20/0 = 0 +26:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:20/0/physics_layer_0/angular_velocity = 0.0 +27:20/0 = 0 +27:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:20/0/physics_layer_0/angular_velocity = 0.0 +28:20/0 = 0 +28:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:20/0/physics_layer_0/angular_velocity = 0.0 +29:20/0 = 0 +29:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:20/0/physics_layer_0/angular_velocity = 0.0 +30:20/0 = 0 +30:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:20/0/physics_layer_0/angular_velocity = 0.0 +31:20/0 = 0 +31:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:20/0/physics_layer_0/angular_velocity = 0.0 +32:20/0 = 0 +32:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:20/0/physics_layer_0/angular_velocity = 0.0 +33:20/0 = 0 +33:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:20/0/physics_layer_0/angular_velocity = 0.0 +34:20/0 = 0 +34:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:20/0/physics_layer_0/angular_velocity = 0.0 +35:20/0 = 0 +35:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:20/0/physics_layer_0/angular_velocity = 0.0 +36:20/0 = 0 +36:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:20/0/physics_layer_0/angular_velocity = 0.0 +37:20/0 = 0 +37:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:20/0/physics_layer_0/angular_velocity = 0.0 +38:20/0 = 0 +38:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:20/0/physics_layer_0/angular_velocity = 0.0 +39:20/0 = 0 +39:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:20/0/physics_layer_0/angular_velocity = 0.0 +40:20/0 = 0 +40:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:20/0/physics_layer_0/angular_velocity = 0.0 +41:20/0 = 0 +41:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:20/0/physics_layer_0/angular_velocity = 0.0 +42:20/0 = 0 +42:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:20/0/physics_layer_0/angular_velocity = 0.0 +43:20/0 = 0 +43:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:20/0/physics_layer_0/angular_velocity = 0.0 +44:20/0 = 0 +44:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:20/0/physics_layer_0/angular_velocity = 0.0 +45:20/0 = 0 +45:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:20/0/physics_layer_0/angular_velocity = 0.0 +46:20/0 = 0 +46:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:20/0/physics_layer_0/angular_velocity = 0.0 +47:20/0 = 0 +47:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:20/0/physics_layer_0/angular_velocity = 0.0 +48:20/0 = 0 +48:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:20/0/physics_layer_0/angular_velocity = 0.0 +0:21/0 = 0 +0:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:21/0/physics_layer_0/angular_velocity = 0.0 +1:21/0 = 0 +1:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:21/0/physics_layer_0/angular_velocity = 0.0 +2:21/0 = 0 +2:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:21/0/physics_layer_0/angular_velocity = 0.0 +3:21/0 = 0 +3:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:21/0/physics_layer_0/angular_velocity = 0.0 +4:21/0 = 0 +4:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:21/0/physics_layer_0/angular_velocity = 0.0 +5:21/0 = 0 +5:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:21/0/physics_layer_0/angular_velocity = 0.0 +6:21/0 = 0 +6:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:21/0/physics_layer_0/angular_velocity = 0.0 +7:21/0 = 0 +7:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:21/0/physics_layer_0/angular_velocity = 0.0 +8:21/0 = 0 +8:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:21/0/physics_layer_0/angular_velocity = 0.0 +9:21/0 = 0 +9:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:21/0/physics_layer_0/angular_velocity = 0.0 +10:21/0 = 0 +10:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:21/0/physics_layer_0/angular_velocity = 0.0 +11:21/0 = 0 +11:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:21/0/physics_layer_0/angular_velocity = 0.0 +12:21/0 = 0 +12:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:21/0/physics_layer_0/angular_velocity = 0.0 +13:21/0 = 0 +13:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:21/0/physics_layer_0/angular_velocity = 0.0 +14:21/0 = 0 +14:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:21/0/physics_layer_0/angular_velocity = 0.0 +15:21/0 = 0 +15:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:21/0/physics_layer_0/angular_velocity = 0.0 +16:21/0 = 0 +16:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:21/0/physics_layer_0/angular_velocity = 0.0 +17:21/0 = 0 +17:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:21/0/physics_layer_0/angular_velocity = 0.0 +18:21/0 = 0 +18:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:21/0/physics_layer_0/angular_velocity = 0.0 +19:21/0 = 0 +19:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:21/0/physics_layer_0/angular_velocity = 0.0 +20:21/0 = 0 +20:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:21/0/physics_layer_0/angular_velocity = 0.0 +21:21/0 = 0 +21:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:21/0/physics_layer_0/angular_velocity = 0.0 +22:21/0 = 0 +22:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:21/0/physics_layer_0/angular_velocity = 0.0 +23:21/0 = 0 +23:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:21/0/physics_layer_0/angular_velocity = 0.0 +24:21/0 = 0 +24:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:21/0/physics_layer_0/angular_velocity = 0.0 +25:21/0 = 0 +25:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:21/0/physics_layer_0/angular_velocity = 0.0 +26:21/0 = 0 +26:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:21/0/physics_layer_0/angular_velocity = 0.0 +27:21/0 = 0 +27:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:21/0/physics_layer_0/angular_velocity = 0.0 +28:21/0 = 0 +28:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:21/0/physics_layer_0/angular_velocity = 0.0 +29:21/0 = 0 +29:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:21/0/physics_layer_0/angular_velocity = 0.0 +30:21/0 = 0 +30:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:21/0/physics_layer_0/angular_velocity = 0.0 +31:21/0 = 0 +31:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:21/0/physics_layer_0/angular_velocity = 0.0 +32:21/0 = 0 +32:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:21/0/physics_layer_0/angular_velocity = 0.0 +33:21/0 = 0 +33:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:21/0/physics_layer_0/angular_velocity = 0.0 +34:21/0 = 0 +34:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:21/0/physics_layer_0/angular_velocity = 0.0 +35:21/0 = 0 +35:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:21/0/physics_layer_0/angular_velocity = 0.0 +36:21/0 = 0 +36:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:21/0/physics_layer_0/angular_velocity = 0.0 +37:21/0 = 0 +37:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:21/0/physics_layer_0/angular_velocity = 0.0 +38:21/0 = 0 +38:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:21/0/physics_layer_0/angular_velocity = 0.0 +39:21/0 = 0 +39:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:21/0/physics_layer_0/angular_velocity = 0.0 +40:21/0 = 0 +40:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:21/0/physics_layer_0/angular_velocity = 0.0 +41:21/0 = 0 +41:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:21/0/physics_layer_0/angular_velocity = 0.0 +42:21/0 = 0 +42:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:21/0/physics_layer_0/angular_velocity = 0.0 +43:21/0 = 0 +43:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:21/0/physics_layer_0/angular_velocity = 0.0 +44:21/0 = 0 +44:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:21/0/physics_layer_0/angular_velocity = 0.0 +45:21/0 = 0 +45:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:21/0/physics_layer_0/angular_velocity = 0.0 +46:21/0 = 0 +46:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:21/0/physics_layer_0/angular_velocity = 0.0 +47:21/0 = 0 +47:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:21/0/physics_layer_0/angular_velocity = 0.0 +48:21/0 = 0 +48:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:21/0/physics_layer_0/angular_velocity = 0.0 +18:0/0 = 0 +18:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:0/0/physics_layer_0/angular_velocity = 0.0 +18:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) + +[sub_resource type="TileSet" id="TileSet_0u0tf"] +physics_layer_0/collision_layer = 1 +sources/1 = SubResource("TileSetAtlasSource_ari5a") + +[node name="Main" type="Node2D"] + +[node name="TileMap" type="TileMap" parent="."] +tile_set = SubResource("TileSet_0u0tf") +format = 2 +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2) + +[node name="chest" parent="." instance=ExtResource("2_win2x")] +position = Vector2(112, 48) + +[node name="player" parent="." instance=ExtResource("2_ekt33")] +position = Vector2(16, 16) diff --git a/src/player/player.gd b/src/player/player.gd new file mode 100644 index 0000000..121aa2b --- /dev/null +++ b/src/player/player.gd @@ -0,0 +1,19 @@ +extends Area2D + +var dir:= Vector2.ZERO +const TILE_SIZE:= 16 + + +func _init() -> void: + add_to_group('player') + +func _ready() -> void: + pass + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + pass + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed("ui_up") diff --git a/src/player/player.tscn b/src/player/player.tscn new file mode 100644 index 0000000..a3e2cd4 --- /dev/null +++ b/src/player/player.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=4 format=3 uid="uid://bp6oyjqvoyffq"] + +[ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_bwexj"] +[ext_resource type="Script" path="res://src/player/player.gd" id="1_fqi5k"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_v5s8d"] +size = Vector2(16, 16) + +[node name="player" type="Area2D"] +script = ExtResource("1_fqi5k") + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_bwexj") +centered = false +region_enabled = true +region_rect = Rect2(432, 0, 16, 16) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(8, 8) +shape = SubResource("RectangleShape2D_v5s8d") + +[node name="RayCast2D" type="RayCast2D" parent="."] +position = Vector2(8, 8) +target_position = Vector2(0, 16) diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd new file mode 100644 index 0000000..94cffdd --- /dev/null +++ b/src/scene-tiles/chest/chest.gd @@ -0,0 +1,14 @@ +extends Area2D + + +func _init() -> void: + add_to_group('interact') + add_to_group('chest') + +func _ready() -> void: + pass + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + pass diff --git a/src/scene-tiles/chest/chest.tscn b/src/scene-tiles/chest/chest.tscn new file mode 100644 index 0000000..67fb56a --- /dev/null +++ b/src/scene-tiles/chest/chest.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=4 format=3 uid="uid://cojb8qcua33fo"] + +[ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_dpxiw"] +[ext_resource type="Script" path="res://src/scene-tiles/chest/chest.gd" id="1_j2k5u"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_vdfc5"] +size = Vector2(16, 16) + +[node name="chest" type="Area2D"] +script = ExtResource("1_j2k5u") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(8, 8) +shape = SubResource("RectangleShape2D_vdfc5") + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_dpxiw") +centered = false +hframes = 2 +region_enabled = true +region_rect = Rect2(128, 96, 32, 16) From 38523d62f589b03ed0dcd1ca3eb0cbd628fe65ae Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 16 Mar 2024 17:03:28 -0400 Subject: [PATCH 34/86] process based movement system --- src/player/player.gd | 41 ++++++++++++++++++++++++++++++++++------- src/player/player.tscn | 1 - 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/player/player.gd b/src/player/player.gd index 121aa2b..2b2128d 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -1,19 +1,46 @@ extends Area2D -var dir:= Vector2.ZERO +@onready var raycast := $RayCast2D + +var input_dir:= Vector2.ZERO const TILE_SIZE:= 16 func _init() -> void: add_to_group('player') -func _ready() -> void: - pass +#func get_player_input() -> Vector2: + ## make vector representing player input + #var dir := Vector2.ZERO + ##dir.x = Input.get_axis("ui_left","ui_right") + ##dir.y = Input.get_axis("ui_up","ui_down") + #if Input.is_action_just_pressed("ui_up"): + #dir.y += -1 + #if Input.is_action_just_pressed("ui_down"): + #dir.y += 1 + #if Input.is_action_just_pressed("ui_left"): + #dir.x += -1 + #if Input.is_action_just_pressed("ui_right"): + #dir.x += 1 + ## prioritizes left/right movement to up/down movement in diagonal inputs. + #if dir.x != 0 and dir.y != 0: + #dir.y = 0 + #return dir +#func _process(delta: float) -> void: + ##check what group the next tile is in based on your raycast + #input_dir = get_player_input() + #if input_dir == Vector2.ZERO: + #return + #raycast.target_position = input_dir * TILE_SIZE + ## should make some sort of tileItem class + #var next_tile :Object = raycast.get_collider() + #if next_tile == null: + #return + #print(next_tile) + #position += input_dir * TILE_SIZE -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: - pass func _unhandled_input(event: InputEvent) -> void: - if event.is_action_pressed("ui_up") + if event.is_action_pressed("ui_up"): + print('up') \ No newline at end of file diff --git a/src/player/player.tscn b/src/player/player.tscn index a3e2cd4..d916dbf 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -21,4 +21,3 @@ shape = SubResource("RectangleShape2D_v5s8d") [node name="RayCast2D" type="RayCast2D" parent="."] position = Vector2(8, 8) -target_position = Vector2(0, 16) From 58aa1abb2eec387f22332c57eb60e05fa9592cb1 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 16 Mar 2024 17:19:02 -0400 Subject: [PATCH 35/86] next tile checking tile based movement --- src/player/player.gd | 57 +++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/src/player/player.gd b/src/player/player.gd index 2b2128d..e56dd66 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -9,38 +9,31 @@ const TILE_SIZE:= 16 func _init() -> void: add_to_group('player') -#func get_player_input() -> Vector2: - ## make vector representing player input - #var dir := Vector2.ZERO - ##dir.x = Input.get_axis("ui_left","ui_right") - ##dir.y = Input.get_axis("ui_up","ui_down") - #if Input.is_action_just_pressed("ui_up"): - #dir.y += -1 - #if Input.is_action_just_pressed("ui_down"): - #dir.y += 1 - #if Input.is_action_just_pressed("ui_left"): - #dir.x += -1 - #if Input.is_action_just_pressed("ui_right"): - #dir.x += 1 - ## prioritizes left/right movement to up/down movement in diagonal inputs. - #if dir.x != 0 and dir.y != 0: - #dir.y = 0 - #return dir - -#func _process(delta: float) -> void: - ##check what group the next tile is in based on your raycast - #input_dir = get_player_input() - #if input_dir == Vector2.ZERO: - #return - #raycast.target_position = input_dir * TILE_SIZE - ## should make some sort of tileItem class - #var next_tile :Object = raycast.get_collider() - #if next_tile == null: - #return - #print(next_tile) - #position += input_dir * TILE_SIZE +func get_input_vector(event:InputEvent) -> Vector2: + # make vector representing player input + var dir := Vector2.ZERO + #dir.x = Input.get_axis("ui_left","ui_right") + #dir.y = Input.get_axis("ui_up","ui_down") + if event.is_action_pressed("ui_up"): + dir.y -= 1 + if event.is_action_pressed("ui_down"): + dir.y += 1 + if event.is_action_pressed("ui_left"): + dir.x -= 1 + if event.is_action_pressed("ui_right"): + dir.x += 1 + print(dir) + return dir func _unhandled_input(event: InputEvent) -> void: - if event.is_action_pressed("ui_up"): - print('up') \ No newline at end of file + input_dir = get_input_vector(event) + #check what group the next tile is in based on your raycast + if input_dir == Vector2.ZERO: + return + raycast.target_position = input_dir * TILE_SIZE + # should make some sort of tileItem class + var next_tile :Object = raycast.get_collider() + if next_tile != null: + print(next_tile) + position += input_dir * TILE_SIZE \ No newline at end of file From cb4d9369eec7fff62b49d5f653c4c9fef3761b48 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sun, 17 Mar 2024 10:56:42 -0400 Subject: [PATCH 36/86] tile collisions, reset ray before checking again --- src/main/main.tscn | 4 +++- src/player/player.gd | 33 +++++++++++++++++++-------------- src/scene-tiles/chest/chest.gd | 3 --- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/main/main.tscn b/src/main/main.tscn index 92c6fa0..b218b9e 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -3255,10 +3255,12 @@ sources/1 = SubResource("TileSetAtlasSource_ari5a") [node name="TileMap" type="TileMap" parent="."] tile_set = SubResource("TileSet_0u0tf") format = 2 +layer_0/name = "walls" layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2) +layer_1/tile_data = PackedInt32Array() [node name="chest" parent="." instance=ExtResource("2_win2x")] position = Vector2(112, 48) [node name="player" parent="." instance=ExtResource("2_ekt33")] -position = Vector2(16, 16) +position = Vector2(80, 48) diff --git a/src/player/player.gd b/src/player/player.gd index e56dd66..d03051e 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -2,18 +2,17 @@ extends Area2D @onready var raycast := $RayCast2D -var input_dir:= Vector2.ZERO -const TILE_SIZE:= 16 - +const TILE_SIZE := 16 func _init() -> void: - add_to_group('player') + add_to_group("player") + +func _ready() -> void: + raycast.collide_with_areas = true -func get_input_vector(event:InputEvent) -> Vector2: +func get_input_vector(event: InputEvent) -> Vector2: # make vector representing player input var dir := Vector2.ZERO - #dir.x = Input.get_axis("ui_left","ui_right") - #dir.y = Input.get_axis("ui_up","ui_down") if event.is_action_pressed("ui_up"): dir.y -= 1 if event.is_action_pressed("ui_down"): @@ -22,18 +21,24 @@ func get_input_vector(event:InputEvent) -> Vector2: dir.x -= 1 if event.is_action_pressed("ui_right"): dir.x += 1 - print(dir) return dir func _unhandled_input(event: InputEvent) -> void: - input_dir = get_input_vector(event) + var _input_dir := get_input_vector(event) #check what group the next tile is in based on your raycast - if input_dir == Vector2.ZERO: + if _input_dir != Vector2.ZERO: + _move(_input_dir) return - raycast.target_position = input_dir * TILE_SIZE - # should make some sort of tileItem class - var next_tile :Object = raycast.get_collider() + + +func _move(_input_dir:Vector2) -> void: + raycast.target_position = _input_dir * TILE_SIZE + # clear old raycast collison then get new one + raycast.force_raycast_update() + var next_tile: Object = raycast.get_collider() + if next_tile != null: print(next_tile) - position += input_dir * TILE_SIZE \ No newline at end of file + else: + position += _input_dir * TILE_SIZE \ No newline at end of file diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 94cffdd..fa2744b 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -9,6 +9,3 @@ func _ready() -> void: pass -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: - pass From 0acb0fb80327f37d288ab2c5361fd77ab3484efa Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Mon, 18 Mar 2024 14:36:09 -0400 Subject: [PATCH 37/86] text is splayed --- project.godot | 9 ++++++++ src/main/main.gd | 1 + src/main/main.tscn | 38 +++++++++++++++++++++++++++++----- src/main/ui.gd | 10 +++++++++ src/player/player.gd | 21 ++++++++++++++++++- src/player/player.tscn | 1 + src/scene-tiles/chest/chest.gd | 11 ++++++++++ 7 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 src/main/main.gd create mode 100644 src/main/ui.gd diff --git a/project.godot b/project.godot index 32b6d1c..3e84ed0 100644 --- a/project.godot +++ b/project.godot @@ -22,6 +22,15 @@ window/size/viewport_height=144 window/size/window_width_override=1280 window/size/window_height_override=720 window/stretch/mode="viewport" +window/stretch/scale_mode="integer" + +[input] + +inspect={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) +] +} [rendering] diff --git a/src/main/main.gd b/src/main/main.gd new file mode 100644 index 0000000..e251cf8 --- /dev/null +++ b/src/main/main.gd @@ -0,0 +1 @@ +extends Node2D diff --git a/src/main/main.tscn b/src/main/main.tscn index b218b9e..8eca979 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -1,8 +1,10 @@ -[gd_scene load_steps=6 format=3 uid="uid://cv5xm6ru2dkxf"] +[gd_scene load_steps=8 format=3 uid="uid://cv5xm6ru2dkxf"] +[ext_resource type="Script" path="res://src/main/main.gd" id="1_8hq0w"] [ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] [ext_resource type="PackedScene" uid="uid://bp6oyjqvoyffq" path="res://src/player/player.tscn" id="2_ekt33"] [ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="2_win2x"] +[ext_resource type="Script" path="res://src/main/ui.gd" id="4_o4xue"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ari5a"] texture = ExtResource("1_kghfi") @@ -3251,16 +3253,42 @@ physics_layer_0/collision_layer = 1 sources/1 = SubResource("TileSetAtlasSource_ari5a") [node name="Main" type="Node2D"] +script = ExtResource("1_8hq0w") -[node name="TileMap" type="TileMap" parent="."] +[node name="player" parent="." instance=ExtResource("2_ekt33")] +position = Vector2(80, 48) + +[node name="Map" type="Node2D" parent="."] + +[node name="TileMap" type="TileMap" parent="Map"] tile_set = SubResource("TileSet_0u0tf") format = 2 layer_0/name = "walls" layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2) layer_1/tile_data = PackedInt32Array() -[node name="chest" parent="." instance=ExtResource("2_win2x")] +[node name="chest" parent="Map" instance=ExtResource("2_win2x")] position = Vector2(112, 48) -[node name="player" parent="." instance=ExtResource("2_ekt33")] -position = Vector2(80, 48) +[node name="UI" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 0 +offset_right = 256.0 +offset_bottom = 144.0 +script = ExtResource("4_o4xue") + +[node name="Textbox" type="Panel" parent="UI"] +visible = false +layout_mode = 0 +offset_left = 16.0 +offset_top = 96.0 +offset_right = 240.0 +offset_bottom = 128.0 + +[node name="Text" type="Label" parent="UI/Textbox"] +layout_mode = 0 +offset_right = 224.0 +offset_bottom = 32.0 +theme_override_font_sizes/font_size = 10 +text = "I told you to not let Jayden make the ui bruh!!!" +autowrap_mode = 2 diff --git a/src/main/ui.gd b/src/main/ui.gd new file mode 100644 index 0000000..6f0f7e8 --- /dev/null +++ b/src/main/ui.gd @@ -0,0 +1,10 @@ +class_name UI +extends Control + +@onready var textbox:Panel = $Textbox + +func render_text(new_text): + textbox.visible = true + var textLabel = $Textbox/Text + textLabel.text = new_text + pass diff --git a/src/player/player.gd b/src/player/player.gd index d03051e..7ec94c3 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -1,3 +1,4 @@ +class_name player extends Area2D @onready var raycast := $RayCast2D @@ -30,6 +31,9 @@ func _unhandled_input(event: InputEvent) -> void: if _input_dir != Vector2.ZERO: _move(_input_dir) return + if event.is_action_pressed('inspect'): + _inspect() + func _move(_input_dir:Vector2) -> void: @@ -41,4 +45,19 @@ func _move(_input_dir:Vector2) -> void: if next_tile != null: print(next_tile) else: - position += _input_dir * TILE_SIZE \ No newline at end of file + position += _input_dir * TILE_SIZE + + +func _inspect() -> void: + raycast.force_raycast_update() + var inspect_tile: Object = raycast.get_collider() + if inspect_tile == null: + print('wow nothing!') + return + if inspect_tile.is_in_group('chest'): + inspect_tile._on_inspection() + #chest event + pass + + + pass diff --git a/src/player/player.tscn b/src/player/player.tscn index d916dbf..a3e2cd4 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -21,3 +21,4 @@ shape = SubResource("RectangleShape2D_v5s8d") [node name="RayCast2D" type="RayCast2D" parent="."] position = Vector2(8, 8) +target_position = Vector2(0, 16) diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index fa2744b..d3d39fe 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -1,5 +1,11 @@ extends Area2D +signal inspected +var opened:bool = false +@onready var sprite = $Sprite2D + +#bad solution but not a bad solution YET +@onready var ui:UI = get_parent().get_parent().get_node('UI') func _init() -> void: add_to_group('interact') @@ -8,4 +14,9 @@ func _init() -> void: func _ready() -> void: pass +func _on_inspection() -> void: + if !opened: + ui.render_text('I warned you about jayden making ui!!!') + $Sprite2D.frame = 1 + From ee72c04bd9d00b368f66c8868d6acca42f669136 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Mon, 18 Mar 2024 21:36:02 -0400 Subject: [PATCH 38/86] can't act while text is out, paint chests like tiles --- project.godot | 5 +++++ src/main/main.gd | 20 ++++++++++++++++++++ src/main/main.tscn | 15 ++++++++------- src/main/ui.gd | 23 ++++++++++++++++++++--- src/player/player.gd | 9 ++++++--- src/player/player.tscn | 2 +- src/scene-tiles/chest/chest.gd | 4 ++-- src/scene-tiles/chest/chest.tscn | 4 +--- 8 files changed, 63 insertions(+), 19 deletions(-) diff --git a/project.godot b/project.godot index 3e84ed0..8c5872d 100644 --- a/project.godot +++ b/project.godot @@ -31,6 +31,11 @@ inspect={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) ] } +adv_text={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) +] +} [rendering] diff --git a/src/main/main.gd b/src/main/main.gd index e251cf8..f9caa2e 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -1 +1,21 @@ extends Node2D + +@onready var ui:UI = $UI +@onready var player:Player = $Player + +var in_cutscene := false + +func _ready() -> void: + ui.text_rendered.connect(_start_cutscene) + ui.text_removed.connect(_end_cutscene) + pass + + +func _start_cutscene() -> void: + in_cutscene = true + player.is_actionable = false + +func _end_cutscene() -> void: + in_cutscene = false + await get_tree().create_timer(0.01).timeout # 10ms buffer hack to prevent input collision from text advancing and player input, could also solve by checking UI input in player _input event? + player.is_actionable = true \ No newline at end of file diff --git a/src/main/main.tscn b/src/main/main.tscn index 8eca979..19c4d23 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=8 format=3 uid="uid://cv5xm6ru2dkxf"] +[gd_scene load_steps=9 format=3 uid="uid://cv5xm6ru2dkxf"] [ext_resource type="Script" path="res://src/main/main.gd" id="1_8hq0w"] [ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] @@ -3248,14 +3248,18 @@ texture = ExtResource("1_kghfi") 18:0/0/physics_layer_0/angular_velocity = 0.0 18:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +[sub_resource type="TileSetScenesCollectionSource" id="TileSetScenesCollectionSource_mi6dp"] +scenes/1/scene = ExtResource("2_win2x") + [sub_resource type="TileSet" id="TileSet_0u0tf"] physics_layer_0/collision_layer = 1 sources/1 = SubResource("TileSetAtlasSource_ari5a") +sources/3 = SubResource("TileSetScenesCollectionSource_mi6dp") [node name="Main" type="Node2D"] script = ExtResource("1_8hq0w") -[node name="player" parent="." instance=ExtResource("2_ekt33")] +[node name="Player" parent="." instance=ExtResource("2_ekt33")] position = Vector2(80, 48) [node name="Map" type="Node2D" parent="."] @@ -3264,11 +3268,8 @@ position = Vector2(80, 48) tile_set = SubResource("TileSet_0u0tf") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2) -layer_1/tile_data = PackedInt32Array() - -[node name="chest" parent="Map" instance=ExtResource("2_win2x")] -position = Vector2(112, 48) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 196617, 0, 131072) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 262152, 3, 65536, 327689, 3, 65536, 327690, 3, 65536, 327691, 3, 65536, 262156, 3, 65536, 196620, 3, 65536, 131084, 3, 65536, 131083, 3, 65536, 131082, 3, 65536, 131081, 3, 65536, 196617, 3, 65536, 196616, 3, 65536, 327688, 3, 65536, 393224, 3, 65536, 393225, 3, 65536, 458761, 3, 65536, 458762, 3, 65536, 458763, 3, 65536, 458764, 3, 65536, 393228, 3, 65536, 393229, 3, 65536, 327693, 3, 65536, 262157, 3, 65536, 196621, 3, 65536, 131085, 3, 65536, 65548, 3, 65536, 65547, 3, 65536, 65546, 3, 65536, 65545, 3, 65536, 65544, 3, 65536, 65549, 3, 65536, 131086, 3, 65536, 196622, 3, 65536, 196623, 3, 65536) [node name="UI" type="Control" parent="."] layout_mode = 3 diff --git a/src/main/ui.gd b/src/main/ui.gd index 6f0f7e8..9d0ea58 100644 --- a/src/main/ui.gd +++ b/src/main/ui.gd @@ -2,9 +2,26 @@ class_name UI extends Control @onready var textbox:Panel = $Textbox +signal text_rendered +signal text_removed +signal text_advanced -func render_text(new_text): + +func render_text(new_text_arr) -> void: + #loop through the array and display the lines of text + text_rendered.emit() textbox.visible = true var textLabel = $Textbox/Text - textLabel.text = new_text - pass + #i = 0 + #while i < new_text_arr.length(): + for line in new_text_arr: + textLabel.text = line + await text_advanced + #await text_advanced + textbox.visible = false + text_removed.emit() + +func _input(event: InputEvent) -> void: + if event.is_action_pressed("adv_text"): + text_advanced.emit() + diff --git a/src/player/player.gd b/src/player/player.gd index 7ec94c3..db267f8 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -1,9 +1,10 @@ -class_name player +class_name Player extends Area2D @onready var raycast := $RayCast2D const TILE_SIZE := 16 +var is_actionable:= true func _init() -> void: add_to_group("player") @@ -25,7 +26,10 @@ func get_input_vector(event: InputEvent) -> Vector2: return dir -func _unhandled_input(event: InputEvent) -> void: +func _input(event: InputEvent) -> void: + # don't do anything if you aren't allowed to + if !is_actionable: + return var _input_dir := get_input_vector(event) #check what group the next tile is in based on your raycast if _input_dir != Vector2.ZERO: @@ -56,7 +60,6 @@ func _inspect() -> void: return if inspect_tile.is_in_group('chest'): inspect_tile._on_inspection() - #chest event pass diff --git a/src/player/player.tscn b/src/player/player.tscn index a3e2cd4..e362576 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -6,7 +6,7 @@ [sub_resource type="RectangleShape2D" id="RectangleShape2D_v5s8d"] size = Vector2(16, 16) -[node name="player" type="Area2D"] +[node name="Player" type="Area2D"] script = ExtResource("1_fqi5k") [node name="Sprite2D" type="Sprite2D" parent="."] diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index d3d39fe..dc4fbc6 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -5,7 +5,7 @@ var opened:bool = false @onready var sprite = $Sprite2D #bad solution but not a bad solution YET -@onready var ui:UI = get_parent().get_parent().get_node('UI') +@onready var ui:UI = get_parent().get_parent().get_parent().get_node('UI') func _init() -> void: add_to_group('interact') @@ -16,7 +16,7 @@ func _ready() -> void: func _on_inspection() -> void: if !opened: - ui.render_text('I warned you about jayden making ui!!!') + ui.render_text(['I warned you about jayden making ui!!!','now it is in an array','songboots would be nice']) $Sprite2D.frame = 1 diff --git a/src/scene-tiles/chest/chest.tscn b/src/scene-tiles/chest/chest.tscn index 67fb56a..9d1385c 100644 --- a/src/scene-tiles/chest/chest.tscn +++ b/src/scene-tiles/chest/chest.tscn @@ -6,16 +6,14 @@ [sub_resource type="RectangleShape2D" id="RectangleShape2D_vdfc5"] size = Vector2(16, 16) -[node name="chest" type="Area2D"] +[node name="Chest" type="Area2D"] script = ExtResource("1_j2k5u") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] -position = Vector2(8, 8) shape = SubResource("RectangleShape2D_vdfc5") [node name="Sprite2D" type="Sprite2D" parent="."] texture = ExtResource("1_dpxiw") -centered = false hframes = 2 region_enabled = true region_rect = Rect2(128, 96, 32, 16) From 33f4eb7c9c5882e25e4f8e599f34e4622a6cd43b Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Tue, 19 Mar 2024 23:02:07 -0400 Subject: [PATCH 39/86] room shuffling and a fake ui --- assets/Not Jam UI Condensed 16.ttf | Bin 0 -> 118342 bytes assets/Not Jam UI Condensed 16.ttf.import | 33 + assets/white.png | Bin 0 -> 99 bytes assets/white.png.import | 34 + src/main/main.gd | 29 +- src/main/main.tscn | 3319 +-------------------- src/main/ui.gd | 2 + src/maps/map-1.tscn | 17 + src/maps/map-2.tscn | 15 + src/maps/map-3.tscn | 15 + src/maps/map.gd | 12 + src/player/player.gd | 9 +- src/player/player.tscn | 8 +- src/resources/map_tileset.tres | 3256 ++++++++++++++++++++ src/scene-tiles/chest/chest.gd | 3 +- src/scene-tiles/stairs/stairs.gd | 8 + src/scene-tiles/stairs/stairs.tscn | 18 + 17 files changed, 3509 insertions(+), 3269 deletions(-) create mode 100644 assets/Not Jam UI Condensed 16.ttf create mode 100644 assets/Not Jam UI Condensed 16.ttf.import create mode 100644 assets/white.png create mode 100644 assets/white.png.import create mode 100644 src/maps/map-1.tscn create mode 100644 src/maps/map-2.tscn create mode 100644 src/maps/map-3.tscn create mode 100644 src/maps/map.gd create mode 100644 src/resources/map_tileset.tres create mode 100644 src/scene-tiles/stairs/stairs.gd create mode 100644 src/scene-tiles/stairs/stairs.tscn diff --git a/assets/Not Jam UI Condensed 16.ttf b/assets/Not Jam UI Condensed 16.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c8767d2b229c3b58ca81886f1ffe1e9a29637a5c GIT binary patch literal 118342 zcmeHQ3(RFzbzbNHhgW&27(fvD1qvw0LlkMGx^*T}P_Y3-Q5zj+h5=z1WI(`bxveIe zXsS(ZG_g&6C8FY^(F9X9+_bgQps_w$HJV~7iCUXBv6|W_{Qb_^XWjYFx9`4dpL@=I z{KNhych*^ZJ@?vc?Y+<A-Xn#G94-S{mGib;dFds<3MpRk3&2BPa^<;Cf7Q=#{}7rk z0{)sEd$!+v=@FN`No4gsA}gQSedC?iK6utoPY3HZDPDa4b-T9je8t`0{y2EQh|h)B zq2b^^SsmcG)OXr-dv3kst2ltZ_u=!K8~5(mE>}G7I+267L7(i|e#g!7z2aKXjtA4) zP22bE`p_G`3*A>AA+qJmH}Bndt6VP^z`t*oba)C@k<Y#P?vK6t=!<^|9yEx&>8bZ$ zy%Dau)e=1vCQ6A)X4S1b^kV?bt-87$Nd0$L)pA#{Q?996R+KP;E5-YZcgsPtWd&+Q z)<57OjxUg^lirt#-&?IkuX)~!&JibTryN!L;AFT~6zgAGhhxK)0oc~?asE?@4nY|p zLayZSpVFq3#{ku5;M>c#5zYCw5gj}wt<+WNQ8+|n{i*B#Rh|{JtIZJ{?5CG)l^<mr zjtkfHb0kyJN*>U)Z3V~rsc2HuOE>@xAMH;i16*a*zY?$P1L*NspPkp)un*ZP9)N0J zb&X<J^Q<`UYeiT70ouxAd>U~Tv^o5T_KK#*fR+7$ms<r~6`zI5S3>-i>Pph%@jr&I zc&%(HE(iV?{43j!ls}TY<sP|j?VeMPT1V!fWlcUPAD2)2mi1q(|NHuI{l4`tJ@}1( zySYjcFy+5G0y&y9O@(rPU&RD?$Pcl&yb8(r&mxcgjmYEPiIm3raqNvE$KmsY^YFPx z<b?keIq~;JPI|n^lby(^Xg~c-ku$MwoV`ut+>0@-K1Sr3Zx#8Smy7)F+4%fK<T+my zaaV~v|9+8euMv5{P~`GkMXtc->d%W@^8=ATz-PON?D&AlZnWR<dm?*|5ZMd4eXwyG z^xp~jH{<iie<|`-`0{q>c_%*af{s7?w#Z++N#uRM68WpUMLr1pBVQHyDD-{|ZJ+p} z$S1!m@+ruD2LAmGY<=!Jk$WE!`CA-+39`dyi2NP&{o_3%|MU})2L>Wv`<%!(wupQa zcK`K<BHu&X4_+klAn+e;6L|>m$7hQC6vsb%NaVj>F7orUMSh7m{Oa=}zefAR(7XO7 zDT*7VSh+`vEm$iLxmb$BA0x%l?~&s1sQhD}A;k#~Npa!_q&R7(6l-sn;>q_*aq6K` zoQAeDAbaLjQaojV&u^r7+C@^F|89JKA;r_dcL6@nd=0h$Z<XR=eBAL;Y}+Qq3qB&n zW%#`KetDdfe}k0)=B7iin>bpIk>lh<IayAXGvq8e7i;3P<k|9E*(#R^-0kNNHXZsu z#Qznnjuwcc|D|>H3J0^rOIs7|AybM$;S$EB^O&HkZsS<UpowFNnkhYqy|<=T;U2}R zZ~8^01?&OSYT$+P61h@dCa;uN%MRHsH^^SuC%4NV%3bmnd7HdL-X(u7@0It<U(1K( zqw)#)w0u_Xl`qJB^7rx;c|g7{-;(dh_vOL<>ZzZq>|YBq$B&l6VH1CZa3TDWL6bkw z=O)u1G3b`Qz&`s&_<`pC%xjZtnQ>HRW1eKXg<JAn>0Rx2mACxIE~H#ZW-zyPUU&MR zZJHW`b!;$suF$z4n3Ie-B*u@t^`je+$5o8U^oV@Sp8C%)m4AKE^e3o&WKvQsrt<mT zgFB)(*6wQlY3Y`n>Q|V`&wNirL$}(SdyT<iS4CHIlXAk`3l5v|oKsvACeHRre^BGn zw9oV)r+sf#3f+(7qVh3)*0|bL$o8~dA<n*$bHf?T_q>;#du}#o_wJZbE?M(2GRsG~ zhQZ#D=*+KpAUA00P4y$F#fbf2{%3pAw6A_zFwh&ZuX?y&K`kP4lhzkM3gB+ZpDLHC zw=cd_J?g*0wsOpWaJf3++K+2o`-#>y#NEcV!J50Fw>h3r&=_CFk41w>+qo<1Z`T<@ z^Hw3RWwCZEE?wy(yF(n65v}Vkxt<W@iQ~{W-FpeGWOv!d+sJQ?bJy`R<p<4i9oeP! zO*h_$m-EepYnrVp8Oh|TeA1}YkXM;l^hWK@>%pzMN?#CFZw2Nkd)u~`cLec=2&7+U zY!#7|`HuI)K`z$O(CApO>mGpZm-lkfR*wZB{wCs%=!~;G(-~)e#t*9OVb$EQW{w>t z2zuRhM7gIU`ha=>!q^^*90k$Q?A-K!bvO;T=<$JW>@J=o9IJyv=Qq94tkx<q_h zxh)Vx1UHOb5G&AK<wb1N2IM0I8l&ZFTri7F8Y8`*R^Cepd`KCqNj&J^#6EB)^1ddZ z4-I`S?FBO|$8gcOKZhQ)7{h7r2lYPolk#E~v{-Fxd+Ir=@(1e)<z7Ii+>7c-<#W(b zRy6Skc2oI=wZ57^sz>z^wBi@klJ{O}tEeQJpP0_L#c$D7-?H+h`jy&`WjlxA{24U! z4_MVRp7TfT!zO?0wV<VZkiW6<No{AozVTC_P$rziG@qBTo)uV{`5&Ef)l5<6hvtLA z*jbg*6$be-0HvHyNpDPFw4L+>c1jCl>;!ftjW5VcuU)03{DTksaTmdvk8zdj+RpNf zs~v`^d~0CrC+`=Y^XQ11lq<0u4037M)Dz^SYtmIdHuth$fj-0Uk$!`3Zn=#PjjfT? zcIIQ;wbZZtr$bTy_sABW*RlOQI_rC``8aIi!Jc&1boIl4(_UBL`U>iZ`p5Ln^?`to z&3iuzpmwCI9)^})=2x8M+Ty1`pr5s&e139i>Ij{3)kqn6YMrA&OQnbTIPXS$l%H+e zSufjFeGDx=vo3tJ5H=&fV|+2WuI(((xQqB}@!^SnWa})i6D>_G#MTyW=bU2P$}#0< zKF(?7W5{w$XMEY#KFfcz2CbZRb*?iX<I2Y{l~3g?{#n!24~3RJ|ID64oKvsg^R?f( z*DSi^d)L=GMe7gmr?iG*=Sj@Zwc8dqb3S!!V|)l8e9|cHhpFw%*A~y~2rnar=2#3` z^CZi4o#!okv06|+0(q*j*8VwYF0(cQ1AD}0))eQkw<fjK5L*13ozDHY`jcyV>1%r4 zHK(;2tbbZfRHMqT@KIOOZEH^Xxi%SBK86<Gp<t+<zzOz-=AI97ZsU9%<iKz;z5H#7 z#vTO<H{w`-8aT*J{ICkg(?fypr>0$TfkJPi&eFC$Q2EY1(VpQa2}+%X8{4N@es_J) zj0CVMGO;~Cv^}P07||bT4<cH5gV^A2V~*5XXWw3)Lt#`B$7S3-QnQ|d#ie6I>2Vb; z*A7m5je6d4(H!x;*4~E@ff<`ah8)fTr;>xY>EsqQ7ih#NZ+Lb@R#g#;whzYVU3Bgs zd#XP=&at@8y8T2L=yHv8t}_8#bt$uewG-3PP{^Ym;B7~r_yc{zW<SicJ>P3|zh(6? zzlFP6Kl4S}(XZxgz;gJRAaLMnU5D#+)BbkHkL1VlGx=}%ANgPTwX7Gb#UaJv#nHtv z#c{=n#mU8~#Tms}#ks`=#j}cM7tbxW7MBz+EM8JvS-h-xW%24_N7}xt<HGi+7uOn` z7Cw?VC#33sm}*ny@XZHb1<u2OFCxcJss?hTSM6EQ)I<IRabmk|`CT&}>~CO?^auQ; zkLOI~Umr}it9+?2@RR&V)ssAj>s-o^=T4@##Z&dA^0EDC<+|!=Yqu?b-~Pqy$J*I` zD&Chqk#nG`%bqap_qOJ`bL?}OwPu92yU*6wIcX*h<c%4uGrwiOXSzAFw#|HtzboAt zyJDs@-qn6r`SYP*_Vw?7Z*SAi0vl%(gv(W9ZdBf~&J4@ym(H}QGnP41_))@eQH5%I z3|jnM>1x-~qkIZ2{;qVjqtMc~pYJrV_B)3x-Atj`8H2N~Dn3JMi;J~Rcbv`4YD~?h z{aMw#+NA9YSzlLN^(th2+8%=zf8J+rTttIogwIE|V;*vS2CIox2g^=3;uG{Y!f)2A z=DC&E%BRrc-|Telr$Vbg%IDX}F3+;^wejU!Bc<OO<~7w?^SJh7_v@68>239o^d$DX z_nPC}vvAEth0L$*3Yl)<D#wuJn6CJfz$l%+&%Lm^fb+g5kvX?*zARh*bA24}`HTTY zpLJC63Kbmpd!EDZCRkYR1{<=(2F>Xh<Q$IiX?w7L8G=%dLS0i#=bYp_a51@LKEu9P z^xALrgP|24v&N8-jU4sS64)8vZt*jn@oDv{oTaZTUF|5e^yQikDjgy7(bL==HgT>& zvj)1#s~-^<_!HsN+6(x*`qxsvb4^=0-IeY~Uq*9?rLQf&rLQZ!`rW_e_h`-LcmFhc z&PS2gsYT;K4sy&Fjh_Gqrau>$+dhitzL}3J<rVK^to?+}fqd?(?F-KfNBb7eL#8Vp z<IC&&?AP}}y;9V3o#s-o&JtbutelPI>PSAKSLq4^JE?vTp<%)~2+sjQ4QY-ljOA)7 zy>GtF=FjnP7_Z_*oZJ2`z|7YLIOaCy%FNdT%1ySXxv$Wwr670FA?Vaz;b6|VGwd-P zZ*raU`y*$bQ^5p2;|2uKN7Z>))KGIM`X0w&Q_kcky~@upYHwQk0r^Qd+q3#VZ+cLp zezc_S6^4&$hUtvA<zKYC<?o{D`Ck9T84APWGsx9&*u<mz#z7*V>LnP}OMI|W`4{jH zn)ai7!zN##XU_EA<_oK?{HRLZdvMQa9<uZ<nx4-&gZkH6iNWC9%r$F><rZC2z1uhX zYsIIx8h3TgF1m(hZD0GT(6V<r82Z2WyR_#H=&Y+Up<`aoylxHuf;x@xbA9o7w1u1X z=c9?R_Pi!q`YgI5e^U9GuPvU}$h<}lX^t5*ajr?8OBfIMNuODxoWqW4gK>+0v(wx5 zH=p+gHNCL`>EI*kCc_|)4gO$_8#eW~rnj{h;Sc)J)vuQFX1!~EV_+KBxV1e7E&i@_ zwrlBAev5C`^iyD9`g`^_Nb|eoOS3mdHMuH7A~4AFL_TXz$#$(@!?5&C>nHnR)|HiK zKAPa7y0dU+@LTk@`c)sxX}iMX!LUj0NAg%&_X9cS%p9XRx+{O@T*Jt~2dOI<2Xn@s zT3VdhdnuM?j@-D<8F!2zxGM5GH&ULo-lJ@Gd5uE^T61;pb>T-xqII&_=xzNyQ}8#F zI$io2MaO-#G#7_W{D7-X?Pmm9wa07XqrMh>_Q=$8$A!p1S()Z}t{t*l_`KmA@-E@; zRee_O75^JFUy%po>+&u64yyeC{X;PQh}8K#@8?ta`5Asjneop2bwAPTM!#ctU@uWl z^+n}}<Lxs)kH^x_A3my5_YUbrduXOJ-j;vS@|M5nfkEanUv2t13W0JP_x+svR&6j{ zYfxgfHfY)#@w@Tu=2{<-Q@xhF@+pk|)_kl#WWR0vW<Iz0(Um&781A0u21}nscjQms z{Fc5`z#zTN6-zT8pi^#B*Y%+3|I%Hj^3l~OhY$nMxUSWepY?UcPlba1?ghMKxpwR5 zn%kKDz{cXKt3!}|gNVMEome~R3G58V+u{DC_QPCle3THr#O!50#$BzaYdgy`u67uv z^Hui<WQYhY{dbmh^!YkRtli40uJo8)ZI5PMY;?GN*0?jWwEDh!tM9Y*z7IeMyqEP% zVvSi_e%9AkJ{V&tfKK%q2Mfjzr23{+fyb^hK4|8e)^TjU3C7+T^)&BXu>3g!yO-g_ z-!*Gp&l)p^*8N=N4_0&<lh!fU7%1d1&~}C8JHlke;aXtIde}NXu}ix!>Z<H<-C$pD z5<&l)^O*Ney-bJbSYtk%R?k6YuF`L(jEz1FdK+~lc~($*kVzmkJXKue3>=n~GVZ;Y z;X5S9y{nLaBh%jp80&v5L+0JC6&b)mGrrL)M|J!I`MN!j8#eW-+|2n5KSzE<{NuX@ z(YNclNPcm<g(DXmc^czi6d(JO?nl1YUFKL7Kc2NLT;&)B>#33LbHAtF)}IJ}@@%fz znVywt)t0K)vfGueekio`DPMJ-ko=zHjceS@S250M##3{g`K+2^I@?v;+S{5dLh2YX zUt3(qnj!09`lEPWE(D`o&H(ki!#NS)#IJG;gL$^r&wPpp{G~@5{OX-<_`|iNelpDS za%8t=)tuJg$za6uf1S@gW<E<#IzQp8U_3RORIYWl8`;eIxT@7I!@14;nhnSW_$KgU zJhbR6$NY>lzv333$Vp)7dY^3}Im_pBI_B0`Gd*_IQ1vNH&HX?>tpJ>}79PyZ>0{f> zJu4Sd^~U&Ee|!9Cs21159D0|$McyXkpW|Feu1=bBQ)rrl7UcP{H9zHQpsy?4!J`ek zA@(o1#>kIkIhkzVJOha3zP87pMAiZ2pEX_WD75Uw_@<RpeF{Z>8>;&LzQj`2HoED1 zUFW_v-!q+SMDf&|SN`5>nQE}B{$QO$;1COq9u5rL5nXYX)Aks&_!m#F?tRfcmgD3^ zIayA{J&?2HT)9A=CC`@U%2v4qRo2rVI__gOWhQfGcg3xYDYK_l2Jy(Y#h(CsZmMT= zcJwz&lLlMo0)<^ipm+H}Gs8xHQv1@4yp<`g&cu-KbTsw74!(Cj*)%EBVl;HtRk4_I z4v}F~K3H`qQ#6ADzS_Rh6<Vt*pWUe(!$41}U(`P<)649cILG;D3;gqZ%&+YX`{L_M zkNRin%kOR(TC;NJoZ>O)8$TBc@omn|*HR~42PnVK+1t)2HrvgzooAc?kIgtb7r1&( z=m;Mkk{$!!?EJ~s2wcmVnfWaoHPV>*4}5<Ae%G$^!osRPs8FiBV9!8wmJjwcRC$Z0 zo0Zac23z`OO<#k7KJEeDwfL2ZbB*z(&sC##EdLL<+;y~CAX6u<9(a~yM)zVCHvgvX z#t<4Gt&TawH8c15*ziB_C&JIQVx3=@wWGOc<)HE@wD@ODS3eY5_F{Z2$M~bU_98iG z){-F?<od8#<Gs@jf4HW&e~MeR#`Ii!w61Y&S@>hYfZyUo9PRHF^|F%bNHesqG%}qt zp)DTG9FCal7-7~I;wPdB&m<*{!6mZs8E5}{UcHP<@@}E8N*826xhEriJdR3_wny}+ zoI+~`ispm&vK*qxJ4lN!Cf~MQ?I?`N@24LRmSz3DU1Ril)Yk_X&oNmu8fDU_?Fv~w z&_8VIx9FX(E$b*L#7M!W)Lw*;>0R;7evL^Z<m!kGo8#B}KBudG^)muzK1*@FILfzK z)7#p6A{^>=jcKl{W4VgLVc$y~<6#q@drqn!5oqNc&zYT9N(89Y9Ot7cbrd0O$hYNZ zebu{`W_mwv?m3ydyNmH5L_Vr@4j~5`_``(ra|?{moxk=QUN`(s#k>A~f%R?i&NbzG zC3Wwl{F_)~^X6xJjJNf-t^AW=0B5;~vwfaB?i_35yH=K>deI#pgF2)68-YQ_Y32`_ za#{hws-*k``8-_ZW9>>;7_}4gi`u!L3#%Lqz}O0lwfoT$#KFs@@}=^N;N2NBx`**$ z`6#Mqll&pDK4z|l!zLbN;G*g3X9QaNGxV<NFS4=G?_@b?%Benuohu9jGPY8@x1i3L zu67h!_F{a~%BenuCqYq{>wV=~w2*3q+rAHV#%YEyOwPQ)czv<8B-$R)Gp%1{#``EB z97g6^d@=d9?P^D1OkU{<MUDllw0?$vX4w~vSY%}RoD_X<)mS(Wna*=#Ykt)`Y}zre z|9P)qjxuG|xU224ofFWGUy*~~)9iz1HtxK&fZM(Yk+}1CE<0}K36ImV<I6U082N&1 zs`4qwlR-1j5cZ01YJS$IcB$RW2k!;kS(16<C^&*Ulz5-Qq<LfN`9b5Ykmql0AHgAx zu&W%M<<|I!?mS&_)`xyH_oN(WrYk-zAHKs_&b!!IOp4zD{~g9)XGQTueNG-1;s@G| z|CCY#-eV_8;}YI`-*{c<ZHw8J^V(VBLiG^aIct3=49<<Ij+9Sfz&`+`9FbZsI1{kw zwVcW`4D?0#x!zZ-Jn>!&>`l%mrZX-i-#5LjKILb>s(T#8aLRpP$~)wyUJJ(M^E}#O zzp$e@n3{XaAJoRM&aOIVna(+@dKjkq!8LF0eIm8Q_D5@OBEQN9dmhbAg`A_>9)lJ? z(;1&uugbAL3s*S{vL1_H>Cb?m^!Dzg@xLe3d@tmtt8r@{K>&R;>)ggZv4Kb5uSR^D z^9<Y84$l$1uFsur^s{aMg7}brj(_iSh#y_4M;XI!tlw?<Eq$}5xAm9#8Mpks2=Q}s zorB7E(|%tbT%NtRHOEX#N9g@%)HTAj!E=*EAJyKlsaM<E*0QxP;r$KoPt<M<26J5< zhZsNWXFMjS?VasWTszNQR_*!h5cu!UVfyB0eT=K!80^a5RX*mIwzGc5@mm|np*Gjf zd*2_yCGTyW`@x=`a&F%AAjdg|Epfzq^7(j6eS&wVm(NJR&y?$M*7cs0J@SG5?({kj zb<T{zwsR@-a~@;ZeP%@LTWb;f$@YZmD4<8|s$SDR`Op1pYcG{Qs86mh#Svimq+Z&P z`7PX$e&%O7;}*X~@2ZdWGtT-MPvt+f`eh)u8eX3^*A|%YR$UDTO+3g^qQmCo9I)tE zFY&E5*J7?U`_y*tto0a!Tz5fCG<F07K8jsHCwcY9tVfP9<1R8r7N12|y{CZ@Bba#K zDrLRweT>`Y1oKC)`wpA+qGJ|)7Q8S1NUrdjH1cOK-p{`HgL`(G8!?EK>9lsl^lJOE z>G$`>2Y51h(w=hayhnF^&trK(?WubK%^#iv(U19#AL6$n=Dn!7#ZTkX_WFm)nRB`y zO&!(!ux;E`51uW+TLe<q*{S0g%$w@Do1CA)S~zI(x28wzCCA;0b62{K%Ni7w&lb3e z^MXF}F=_4WZOnKKQ*mA+dCpk$wY6E>#~3!}L@{vYXPo7k&N%ZEUaq$@U2}h{%;e~E z!pZpww_W8a)o_qcJVy-2%SCIR;sdl9AI4oxKeC!j1$yIad2(+zRu>F<8`N{OR_%Os zeAG@ow=z8%5$z!y8Jj8G&bZ1e6zT2V$2$6f@9cx()%!Gh|E|+i<GOK-XK{=!`-p4a zP(B2^y+za2&j<|sjqvfVKyxHk7v@=t=8li1)KT3J7folsEPs@r`E2~@V3E1qqg~3X znx;}U^V&kbFWbBPu+C-YVf4I(`3M)ngGya8dazo!$jZj;$o{b_AoIoWw(_a`7T>bd zx4^*xo^juQ9VDoIaJVY^&O@HngKH1m=ffcFO0F^cv%uQ8Du<-o=mD?_XHQ1$HC^!$ zgrc!o)V}?2W6zn?FYW8dKke55Ev2W_5AJVl|EY38wWanm#^=2PRr2+VDi%S6H9`y# zvay+`d|m0P=QJof(69ZYhvTY)*Fvp=)U|bLeyUQ{6ZNO9|1J5=UA5+lLZr;Z+*Ce= zo1On0bU;>9uf0yX#utBw>%CYXHtF9ef9t%)%I!zK#$$WqfN#*03+S~zwl~5_K3M&R zP5n&g>z|AV_XJ5_YyL=o*bc7AHR5TmA;{LG`n32gy7x+I@4!uVE!+`5<1Ei~#@q6% zye0P(Fv!XfagSdw-2ZOMcJ;q0s(w^qb;hPvX23_89MEh1Y;S~<JXf%VbA_s2UhxCJ z$S$wc)>*XLIp8bTs-&)TSI-zC=Rwu%*W@qAeVcb(*6joW<>MBsu3?kT)u7qiHtS>S z{zxBHl~uh=52~5;@jA->v%JY4i66_gUa$S=NIeP|E@NF(ev8kds~&~SZ{aEzgDfB8 z)AqLfsd6VGo(@k>45wVb=ekC7R&v${IAy(7SL_}lUjqvC4eLCNWV`BD$oFuxondg6 zNuv!vn!8q_L!YOowlg2&sxJmp`9-Sp!<pY}nQIp6+R+E(jONTxJlI7gW+1Ou!R{?l z4_8c38G||p4SlR9@F!7^#zkRje9T>@W_)UfE5AZZ&Z5WkupHwm$I#-l=&VoiRJqf@ zh$m;T?)P<mxOBCS4!UaoHFCdgt{y1-82jex<)fuh3n2npu6T7+ZMgaQpH$q0PWZor z^*{=&o{Fu=QBwWB1*ofNe}2uiMV=!!*T)Cp*DOC(A0I5I%Rkh|he7r~>f<A!@mKZn zG4gVG1XldtYH@XaT*z_7HTCg|98%m|AFrbQ_WF2>oLu~AeSDA{UVO4XK3I+^K3^Xn z2H6Md<0ECY_-1{4jGSHk3wlv(!QD(bc%`V1(chIr>SOeG<(c&{`n$5VK1P36USA)h zzbl`vkI~<iFW1ND@5;~WWAu0B|LSA(cV%6+;@^34x$Ko&Wlb)V?Xm~(rE)3$--_0o zWT))H|NHR&PPCnm?@V5S<K1$b+z9SlTFSPwv_`hBhUHt}%k`CKr8nn{y!XDBo`-&y zUN<fKeqSZmLF1ad9=*9<cE}Alel0BQmD|zhHMtf?cL2T)^gYO|eK_7LZ>YRjL&Usv z8HYE@ouKUmb+??eb?bST@4a>Hvh91;UV7=;*1b3F+;!8wT|3v#zwnA(yKlR3`z;Y_ zq<O8Dx_Z|w`>x-6)7tsxl<J}VrI(I$pMPO34BJ;-w`=Y7w_U&EhPBt;viJ6z)~?-q z$J*;|+jH~2wY_iHb<5hVAm6zCjd!l?+`IdnoB*>(fN~Bgzc5$+T`L#(gW&%nXvqyZ z0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX z0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX z0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX z0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX0yzRX Z0yzRX0yzRX0yzRX0yzRX0yB%i{{#Nuf{FkD literal 0 HcmV?d00001 diff --git a/assets/Not Jam UI Condensed 16.ttf.import b/assets/Not Jam UI Condensed 16.ttf.import new file mode 100644 index 0000000..dd00f06 --- /dev/null +++ b/assets/Not Jam UI Condensed 16.ttf.import @@ -0,0 +1,33 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://ddjw625xpmwtc" +path="res://.godot/imported/Not Jam UI Condensed 16.ttf-3435f3f176c8ad289519e69fb68982d4.fontdata" + +[deps] + +source_file="res://assets/Not Jam UI Condensed 16.ttf" +dest_files=["res://.godot/imported/Not Jam UI Condensed 16.ttf-3435f3f176c8ad289519e69fb68982d4.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/assets/white.png b/assets/white.png new file mode 100644 index 0000000000000000000000000000000000000000..a449decfda83ba650f4418e380e7f90a7f528cd7 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le v|NQ^|zn+bYL0EN`JFkRk!j*=DDGUtRr&wf`KP(LfDrE3<^>bP0l+XkKc$*s_ literal 0 HcmV?d00001 diff --git a/assets/white.png.import b/assets/white.png.import new file mode 100644 index 0000000..0d60315 --- /dev/null +++ b/assets/white.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://5kstmna3yb6t" +path="res://.godot/imported/white.png-936ea7d0834e1e21adf362ba74ff2135.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/white.png" +dest_files=["res://.godot/imported/white.png-936ea7d0834e1e21adf362ba74ff2135.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 diff --git a/src/main/main.gd b/src/main/main.gd index f9caa2e..0fa48e3 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -2,14 +2,41 @@ extends Node2D @onready var ui:UI = $UI @onready var player:Player = $Player +@onready var current_map:Node2D = $Map var in_cutscene := false +var maps:Dictionary = {0:preload('res://src/maps/map-1.tscn'),1:preload('res://src/maps/map-2.tscn'),2:preload('res://src/maps/map-3.tscn')} +var shuffled_maps:Array = [] + +var current_map_id + func _ready() -> void: ui.text_rendered.connect(_start_cutscene) ui.text_removed.connect(_end_cutscene) + player.walked_into_stairs.connect(swap_map) pass +func swap_map() -> void: + #reshuffle rooms if we've visted them all + if shuffled_maps.size() == 0: + shuffled_maps = Array(range(maps.size())) + shuffled_maps.shuffle() + #pick new room from remaining choices + var next_map_id :int = shuffled_maps.pop_front() + var nextMap:Node2D = maps[next_map_id].instantiate() + + #load new map + current_map.queue_free() + add_child(nextMap) + current_map = nextMap + + #move the player to the spawn point + var playerSpawnMarker:Marker2D = nextMap.get_node('PlayerSpawn') + player.position = playerSpawnMarker.position + + + func _start_cutscene() -> void: in_cutscene = true @@ -18,4 +45,4 @@ func _start_cutscene() -> void: func _end_cutscene() -> void: in_cutscene = false await get_tree().create_timer(0.01).timeout # 10ms buffer hack to prevent input collision from text advancing and player input, could also solve by checking UI input in player _input event? - player.is_actionable = true \ No newline at end of file + player.is_actionable = true diff --git a/src/main/main.tscn b/src/main/main.tscn index 19c4d23..0da652a 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -1,3260 +1,12 @@ -[gd_scene load_steps=9 format=3 uid="uid://cv5xm6ru2dkxf"] +[gd_scene load_steps=8 format=3 uid="uid://cv5xm6ru2dkxf"] [ext_resource type="Script" path="res://src/main/main.gd" id="1_8hq0w"] [ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] [ext_resource type="PackedScene" uid="uid://bp6oyjqvoyffq" path="res://src/player/player.tscn" id="2_ekt33"] -[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="2_win2x"] +[ext_resource type="PackedScene" uid="uid://deqm4to4ptnq0" path="res://src/maps/map-1.tscn" id="3_w444g"] [ext_resource type="Script" path="res://src/main/ui.gd" id="4_o4xue"] - -[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ari5a"] -texture = ExtResource("1_kghfi") -1:0/0 = 0 -1:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:0/0/physics_layer_0/angular_velocity = 0.0 -2:0/0 = 0 -2:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:0/0/physics_layer_0/angular_velocity = 0.0 -3:0/0 = 0 -3:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:0/0/physics_layer_0/angular_velocity = 0.0 -4:0/0 = 0 -4:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:0/0/physics_layer_0/angular_velocity = 0.0 -5:0/0 = 0 -5:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:0/0/physics_layer_0/angular_velocity = 0.0 -6:0/0 = 0 -6:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:0/0/physics_layer_0/angular_velocity = 0.0 -7:0/0 = 0 -7:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:0/0/physics_layer_0/angular_velocity = 0.0 -8:0/0 = 0 -8:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:0/0/physics_layer_0/angular_velocity = 0.0 -9:0/0 = 0 -9:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:0/0/physics_layer_0/angular_velocity = 0.0 -10:0/0 = 0 -10:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:0/0/physics_layer_0/angular_velocity = 0.0 -11:0/0 = 0 -11:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:0/0/physics_layer_0/angular_velocity = 0.0 -12:0/0 = 0 -12:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:0/0/physics_layer_0/angular_velocity = 0.0 -13:0/0 = 0 -13:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:0/0/physics_layer_0/angular_velocity = 0.0 -14:0/0 = 0 -14:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:0/0/physics_layer_0/angular_velocity = 0.0 -15:0/0 = 0 -15:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:0/0/physics_layer_0/angular_velocity = 0.0 -16:0/0 = 0 -16:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:0/0/physics_layer_0/angular_velocity = 0.0 -17:0/0 = 0 -17:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:0/0/physics_layer_0/angular_velocity = 0.0 -19:0/0 = 0 -19:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:0/0/physics_layer_0/angular_velocity = 0.0 -19:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -20:0/0 = 0 -20:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:0/0/physics_layer_0/angular_velocity = 0.0 -20:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -21:0/0 = 0 -21:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:0/0/physics_layer_0/angular_velocity = 0.0 -22:0/0 = 0 -22:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:0/0/physics_layer_0/angular_velocity = 0.0 -23:0/0 = 0 -23:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:0/0/physics_layer_0/angular_velocity = 0.0 -24:0/0 = 0 -24:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:0/0/physics_layer_0/angular_velocity = 0.0 -25:0/0 = 0 -25:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:0/0/physics_layer_0/angular_velocity = 0.0 -26:0/0 = 0 -26:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:0/0/physics_layer_0/angular_velocity = 0.0 -27:0/0 = 0 -27:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:0/0/physics_layer_0/angular_velocity = 0.0 -28:0/0 = 0 -28:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:0/0/physics_layer_0/angular_velocity = 0.0 -29:0/0 = 0 -29:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:0/0/physics_layer_0/angular_velocity = 0.0 -30:0/0 = 0 -30:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:0/0/physics_layer_0/angular_velocity = 0.0 -31:0/0 = 0 -31:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:0/0/physics_layer_0/angular_velocity = 0.0 -32:0/0 = 0 -32:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:0/0/physics_layer_0/angular_velocity = 0.0 -33:0/0 = 0 -33:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:0/0/physics_layer_0/angular_velocity = 0.0 -34:0/0 = 0 -34:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:0/0/physics_layer_0/angular_velocity = 0.0 -35:0/0 = 0 -35:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:0/0/physics_layer_0/angular_velocity = 0.0 -36:0/0 = 0 -36:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:0/0/physics_layer_0/angular_velocity = 0.0 -37:0/0 = 0 -37:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:0/0/physics_layer_0/angular_velocity = 0.0 -38:0/0 = 0 -38:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:0/0/physics_layer_0/angular_velocity = 0.0 -39:0/0 = 0 -39:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:0/0/physics_layer_0/angular_velocity = 0.0 -40:0/0 = 0 -40:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:0/0/physics_layer_0/angular_velocity = 0.0 -41:0/0 = 0 -41:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:0/0/physics_layer_0/angular_velocity = 0.0 -42:0/0 = 0 -42:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:0/0/physics_layer_0/angular_velocity = 0.0 -43:0/0 = 0 -43:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:0/0/physics_layer_0/angular_velocity = 0.0 -44:0/0 = 0 -44:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:0/0/physics_layer_0/angular_velocity = 0.0 -45:0/0 = 0 -45:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:0/0/physics_layer_0/angular_velocity = 0.0 -46:0/0 = 0 -46:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:0/0/physics_layer_0/angular_velocity = 0.0 -47:0/0 = 0 -47:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:0/0/physics_layer_0/angular_velocity = 0.0 -48:0/0 = 0 -48:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:0/0/physics_layer_0/angular_velocity = 0.0 -0:1/0 = 0 -0:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:1/0/physics_layer_0/angular_velocity = 0.0 -1:1/0 = 0 -1:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:1/0/physics_layer_0/angular_velocity = 0.0 -2:1/0 = 0 -2:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:1/0/physics_layer_0/angular_velocity = 0.0 -3:1/0 = 0 -3:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:1/0/physics_layer_0/angular_velocity = 0.0 -4:1/0 = 0 -4:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:1/0/physics_layer_0/angular_velocity = 0.0 -5:1/0 = 0 -5:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:1/0/physics_layer_0/angular_velocity = 0.0 -6:1/0 = 0 -6:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:1/0/physics_layer_0/angular_velocity = 0.0 -7:1/0 = 0 -7:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:1/0/physics_layer_0/angular_velocity = 0.0 -8:1/0 = 0 -8:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:1/0/physics_layer_0/angular_velocity = 0.0 -9:1/0 = 0 -9:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:1/0/physics_layer_0/angular_velocity = 0.0 -10:1/0 = 0 -10:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:1/0/physics_layer_0/angular_velocity = 0.0 -11:1/0 = 0 -11:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:1/0/physics_layer_0/angular_velocity = 0.0 -12:1/0 = 0 -12:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:1/0/physics_layer_0/angular_velocity = 0.0 -13:1/0 = 0 -13:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:1/0/physics_layer_0/angular_velocity = 0.0 -14:1/0 = 0 -14:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:1/0/physics_layer_0/angular_velocity = 0.0 -15:1/0 = 0 -15:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:1/0/physics_layer_0/angular_velocity = 0.0 -16:1/0 = 0 -16:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:1/0/physics_layer_0/angular_velocity = 0.0 -17:1/0 = 0 -17:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:1/0/physics_layer_0/angular_velocity = 0.0 -18:1/0 = 0 -18:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:1/0/physics_layer_0/angular_velocity = 0.0 -18:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -19:1/0 = 0 -19:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:1/0/physics_layer_0/angular_velocity = 0.0 -20:1/0 = 0 -20:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:1/0/physics_layer_0/angular_velocity = 0.0 -20:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -21:1/0 = 0 -21:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:1/0/physics_layer_0/angular_velocity = 0.0 -22:1/0 = 0 -22:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:1/0/physics_layer_0/angular_velocity = 0.0 -23:1/0 = 0 -23:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:1/0/physics_layer_0/angular_velocity = 0.0 -24:1/0 = 0 -24:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:1/0/physics_layer_0/angular_velocity = 0.0 -25:1/0 = 0 -25:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:1/0/physics_layer_0/angular_velocity = 0.0 -26:1/0 = 0 -26:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:1/0/physics_layer_0/angular_velocity = 0.0 -27:1/0 = 0 -27:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:1/0/physics_layer_0/angular_velocity = 0.0 -28:1/0 = 0 -28:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:1/0/physics_layer_0/angular_velocity = 0.0 -29:1/0 = 0 -29:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:1/0/physics_layer_0/angular_velocity = 0.0 -30:1/0 = 0 -30:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:1/0/physics_layer_0/angular_velocity = 0.0 -31:1/0 = 0 -31:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:1/0/physics_layer_0/angular_velocity = 0.0 -32:1/0 = 0 -32:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:1/0/physics_layer_0/angular_velocity = 0.0 -33:1/0 = 0 -33:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:1/0/physics_layer_0/angular_velocity = 0.0 -34:1/0 = 0 -34:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:1/0/physics_layer_0/angular_velocity = 0.0 -35:1/0 = 0 -35:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:1/0/physics_layer_0/angular_velocity = 0.0 -36:1/0 = 0 -36:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:1/0/physics_layer_0/angular_velocity = 0.0 -37:1/0 = 0 -37:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:1/0/physics_layer_0/angular_velocity = 0.0 -38:1/0 = 0 -38:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:1/0/physics_layer_0/angular_velocity = 0.0 -39:1/0 = 0 -39:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:1/0/physics_layer_0/angular_velocity = 0.0 -40:1/0 = 0 -40:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:1/0/physics_layer_0/angular_velocity = 0.0 -41:1/0 = 0 -41:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:1/0/physics_layer_0/angular_velocity = 0.0 -42:1/0 = 0 -42:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:1/0/physics_layer_0/angular_velocity = 0.0 -43:1/0 = 0 -43:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:1/0/physics_layer_0/angular_velocity = 0.0 -44:1/0 = 0 -44:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:1/0/physics_layer_0/angular_velocity = 0.0 -45:1/0 = 0 -45:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:1/0/physics_layer_0/angular_velocity = 0.0 -46:1/0 = 0 -46:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:1/0/physics_layer_0/angular_velocity = 0.0 -47:1/0 = 0 -47:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:1/0/physics_layer_0/angular_velocity = 0.0 -48:1/0 = 0 -48:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:1/0/physics_layer_0/angular_velocity = 0.0 -0:2/0 = 0 -0:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:2/0/physics_layer_0/angular_velocity = 0.0 -1:2/0 = 0 -1:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:2/0/physics_layer_0/angular_velocity = 0.0 -2:2/0 = 0 -2:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:2/0/physics_layer_0/angular_velocity = 0.0 -3:2/0 = 0 -3:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:2/0/physics_layer_0/angular_velocity = 0.0 -4:2/0 = 0 -4:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:2/0/physics_layer_0/angular_velocity = 0.0 -5:2/0 = 0 -5:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:2/0/physics_layer_0/angular_velocity = 0.0 -6:2/0 = 0 -6:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:2/0/physics_layer_0/angular_velocity = 0.0 -7:2/0 = 0 -7:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:2/0/physics_layer_0/angular_velocity = 0.0 -8:2/0 = 0 -8:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:2/0/physics_layer_0/angular_velocity = 0.0 -9:2/0 = 0 -9:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:2/0/physics_layer_0/angular_velocity = 0.0 -10:2/0 = 0 -10:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:2/0/physics_layer_0/angular_velocity = 0.0 -11:2/0 = 0 -11:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:2/0/physics_layer_0/angular_velocity = 0.0 -12:2/0 = 0 -12:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:2/0/physics_layer_0/angular_velocity = 0.0 -13:2/0 = 0 -13:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:2/0/physics_layer_0/angular_velocity = 0.0 -14:2/0 = 0 -14:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:2/0/physics_layer_0/angular_velocity = 0.0 -15:2/0 = 0 -15:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:2/0/physics_layer_0/angular_velocity = 0.0 -16:2/0 = 0 -16:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:2/0/physics_layer_0/angular_velocity = 0.0 -17:2/0 = 0 -17:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:2/0/physics_layer_0/angular_velocity = 0.0 -18:2/0 = 0 -18:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:2/0/physics_layer_0/angular_velocity = 0.0 -18:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -19:2/0 = 0 -19:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:2/0/physics_layer_0/angular_velocity = 0.0 -19:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -20:2/0 = 0 -20:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:2/0/physics_layer_0/angular_velocity = 0.0 -20:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) -21:2/0 = 0 -21:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:2/0/physics_layer_0/angular_velocity = 0.0 -22:2/0 = 0 -22:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:2/0/physics_layer_0/angular_velocity = 0.0 -23:2/0 = 0 -23:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:2/0/physics_layer_0/angular_velocity = 0.0 -24:2/0 = 0 -24:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:2/0/physics_layer_0/angular_velocity = 0.0 -25:2/0 = 0 -25:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:2/0/physics_layer_0/angular_velocity = 0.0 -26:2/0 = 0 -26:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:2/0/physics_layer_0/angular_velocity = 0.0 -27:2/0 = 0 -27:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:2/0/physics_layer_0/angular_velocity = 0.0 -28:2/0 = 0 -28:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:2/0/physics_layer_0/angular_velocity = 0.0 -29:2/0 = 0 -29:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:2/0/physics_layer_0/angular_velocity = 0.0 -30:2/0 = 0 -30:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:2/0/physics_layer_0/angular_velocity = 0.0 -31:2/0 = 0 -31:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:2/0/physics_layer_0/angular_velocity = 0.0 -32:2/0 = 0 -32:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:2/0/physics_layer_0/angular_velocity = 0.0 -33:2/0 = 0 -33:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:2/0/physics_layer_0/angular_velocity = 0.0 -34:2/0 = 0 -34:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:2/0/physics_layer_0/angular_velocity = 0.0 -35:2/0 = 0 -35:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:2/0/physics_layer_0/angular_velocity = 0.0 -36:2/0 = 0 -36:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:2/0/physics_layer_0/angular_velocity = 0.0 -37:2/0 = 0 -37:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:2/0/physics_layer_0/angular_velocity = 0.0 -38:2/0 = 0 -38:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:2/0/physics_layer_0/angular_velocity = 0.0 -39:2/0 = 0 -39:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:2/0/physics_layer_0/angular_velocity = 0.0 -40:2/0 = 0 -40:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:2/0/physics_layer_0/angular_velocity = 0.0 -41:2/0 = 0 -41:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:2/0/physics_layer_0/angular_velocity = 0.0 -42:2/0 = 0 -42:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:2/0/physics_layer_0/angular_velocity = 0.0 -43:2/0 = 0 -43:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:2/0/physics_layer_0/angular_velocity = 0.0 -44:2/0 = 0 -44:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:2/0/physics_layer_0/angular_velocity = 0.0 -45:2/0 = 0 -45:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:2/0/physics_layer_0/angular_velocity = 0.0 -46:2/0 = 0 -46:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:2/0/physics_layer_0/angular_velocity = 0.0 -47:2/0 = 0 -47:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:2/0/physics_layer_0/angular_velocity = 0.0 -48:2/0 = 0 -48:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:2/0/physics_layer_0/angular_velocity = 0.0 -0:3/0 = 0 -0:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:3/0/physics_layer_0/angular_velocity = 0.0 -1:3/0 = 0 -1:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:3/0/physics_layer_0/angular_velocity = 0.0 -2:3/0 = 0 -2:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:3/0/physics_layer_0/angular_velocity = 0.0 -3:3/0 = 0 -3:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:3/0/physics_layer_0/angular_velocity = 0.0 -4:3/0 = 0 -4:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:3/0/physics_layer_0/angular_velocity = 0.0 -5:3/0 = 0 -5:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:3/0/physics_layer_0/angular_velocity = 0.0 -6:3/0 = 0 -6:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:3/0/physics_layer_0/angular_velocity = 0.0 -7:3/0 = 0 -7:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:3/0/physics_layer_0/angular_velocity = 0.0 -8:3/0 = 0 -8:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:3/0/physics_layer_0/angular_velocity = 0.0 -9:3/0 = 0 -9:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:3/0/physics_layer_0/angular_velocity = 0.0 -10:3/0 = 0 -10:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:3/0/physics_layer_0/angular_velocity = 0.0 -11:3/0 = 0 -11:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:3/0/physics_layer_0/angular_velocity = 0.0 -12:3/0 = 0 -12:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:3/0/physics_layer_0/angular_velocity = 0.0 -13:3/0 = 0 -13:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:3/0/physics_layer_0/angular_velocity = 0.0 -14:3/0 = 0 -14:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:3/0/physics_layer_0/angular_velocity = 0.0 -15:3/0 = 0 -15:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:3/0/physics_layer_0/angular_velocity = 0.0 -16:3/0 = 0 -16:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:3/0/physics_layer_0/angular_velocity = 0.0 -17:3/0 = 0 -17:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:3/0/physics_layer_0/angular_velocity = 0.0 -18:3/0 = 0 -18:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:3/0/physics_layer_0/angular_velocity = 0.0 -19:3/0 = 0 -19:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:3/0/physics_layer_0/angular_velocity = 0.0 -20:3/0 = 0 -20:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:3/0/physics_layer_0/angular_velocity = 0.0 -21:3/0 = 0 -21:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:3/0/physics_layer_0/angular_velocity = 0.0 -22:3/0 = 0 -22:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:3/0/physics_layer_0/angular_velocity = 0.0 -23:3/0 = 0 -23:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:3/0/physics_layer_0/angular_velocity = 0.0 -24:3/0 = 0 -24:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:3/0/physics_layer_0/angular_velocity = 0.0 -25:3/0 = 0 -25:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:3/0/physics_layer_0/angular_velocity = 0.0 -26:3/0 = 0 -26:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:3/0/physics_layer_0/angular_velocity = 0.0 -27:3/0 = 0 -27:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:3/0/physics_layer_0/angular_velocity = 0.0 -28:3/0 = 0 -28:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:3/0/physics_layer_0/angular_velocity = 0.0 -29:3/0 = 0 -29:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:3/0/physics_layer_0/angular_velocity = 0.0 -30:3/0 = 0 -30:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:3/0/physics_layer_0/angular_velocity = 0.0 -31:3/0 = 0 -31:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:3/0/physics_layer_0/angular_velocity = 0.0 -32:3/0 = 0 -32:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:3/0/physics_layer_0/angular_velocity = 0.0 -33:3/0 = 0 -33:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:3/0/physics_layer_0/angular_velocity = 0.0 -34:3/0 = 0 -34:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:3/0/physics_layer_0/angular_velocity = 0.0 -35:3/0 = 0 -35:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:3/0/physics_layer_0/angular_velocity = 0.0 -36:3/0 = 0 -36:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:3/0/physics_layer_0/angular_velocity = 0.0 -37:3/0 = 0 -37:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:3/0/physics_layer_0/angular_velocity = 0.0 -38:3/0 = 0 -38:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:3/0/physics_layer_0/angular_velocity = 0.0 -39:3/0 = 0 -39:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:3/0/physics_layer_0/angular_velocity = 0.0 -40:3/0 = 0 -40:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:3/0/physics_layer_0/angular_velocity = 0.0 -41:3/0 = 0 -41:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:3/0/physics_layer_0/angular_velocity = 0.0 -42:3/0 = 0 -42:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:3/0/physics_layer_0/angular_velocity = 0.0 -43:3/0 = 0 -43:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:3/0/physics_layer_0/angular_velocity = 0.0 -44:3/0 = 0 -44:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:3/0/physics_layer_0/angular_velocity = 0.0 -45:3/0 = 0 -45:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:3/0/physics_layer_0/angular_velocity = 0.0 -46:3/0 = 0 -46:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:3/0/physics_layer_0/angular_velocity = 0.0 -47:3/0 = 0 -47:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:3/0/physics_layer_0/angular_velocity = 0.0 -48:3/0 = 0 -48:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:3/0/physics_layer_0/angular_velocity = 0.0 -0:4/0 = 0 -0:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:4/0/physics_layer_0/angular_velocity = 0.0 -1:4/0 = 0 -1:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:4/0/physics_layer_0/angular_velocity = 0.0 -2:4/0 = 0 -2:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:4/0/physics_layer_0/angular_velocity = 0.0 -3:4/0 = 0 -3:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:4/0/physics_layer_0/angular_velocity = 0.0 -4:4/0 = 0 -4:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:4/0/physics_layer_0/angular_velocity = 0.0 -5:4/0 = 0 -5:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:4/0/physics_layer_0/angular_velocity = 0.0 -6:4/0 = 0 -6:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:4/0/physics_layer_0/angular_velocity = 0.0 -7:4/0 = 0 -7:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:4/0/physics_layer_0/angular_velocity = 0.0 -8:4/0 = 0 -8:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:4/0/physics_layer_0/angular_velocity = 0.0 -9:4/0 = 0 -9:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:4/0/physics_layer_0/angular_velocity = 0.0 -10:4/0 = 0 -10:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:4/0/physics_layer_0/angular_velocity = 0.0 -11:4/0 = 0 -11:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:4/0/physics_layer_0/angular_velocity = 0.0 -12:4/0 = 0 -12:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:4/0/physics_layer_0/angular_velocity = 0.0 -13:4/0 = 0 -13:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:4/0/physics_layer_0/angular_velocity = 0.0 -14:4/0 = 0 -14:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:4/0/physics_layer_0/angular_velocity = 0.0 -15:4/0 = 0 -15:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:4/0/physics_layer_0/angular_velocity = 0.0 -16:4/0 = 0 -16:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:4/0/physics_layer_0/angular_velocity = 0.0 -17:4/0 = 0 -17:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:4/0/physics_layer_0/angular_velocity = 0.0 -18:4/0 = 0 -18:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:4/0/physics_layer_0/angular_velocity = 0.0 -19:4/0 = 0 -19:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:4/0/physics_layer_0/angular_velocity = 0.0 -20:4/0 = 0 -20:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:4/0/physics_layer_0/angular_velocity = 0.0 -21:4/0 = 0 -21:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:4/0/physics_layer_0/angular_velocity = 0.0 -22:4/0 = 0 -22:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:4/0/physics_layer_0/angular_velocity = 0.0 -23:4/0 = 0 -23:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:4/0/physics_layer_0/angular_velocity = 0.0 -24:4/0 = 0 -24:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:4/0/physics_layer_0/angular_velocity = 0.0 -25:4/0 = 0 -25:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:4/0/physics_layer_0/angular_velocity = 0.0 -26:4/0 = 0 -26:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:4/0/physics_layer_0/angular_velocity = 0.0 -27:4/0 = 0 -27:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:4/0/physics_layer_0/angular_velocity = 0.0 -28:4/0 = 0 -28:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:4/0/physics_layer_0/angular_velocity = 0.0 -29:4/0 = 0 -29:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:4/0/physics_layer_0/angular_velocity = 0.0 -30:4/0 = 0 -30:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:4/0/physics_layer_0/angular_velocity = 0.0 -31:4/0 = 0 -31:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:4/0/physics_layer_0/angular_velocity = 0.0 -32:4/0 = 0 -32:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:4/0/physics_layer_0/angular_velocity = 0.0 -33:4/0 = 0 -33:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:4/0/physics_layer_0/angular_velocity = 0.0 -34:4/0 = 0 -34:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:4/0/physics_layer_0/angular_velocity = 0.0 -35:4/0 = 0 -35:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:4/0/physics_layer_0/angular_velocity = 0.0 -36:4/0 = 0 -36:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:4/0/physics_layer_0/angular_velocity = 0.0 -37:4/0 = 0 -37:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:4/0/physics_layer_0/angular_velocity = 0.0 -38:4/0 = 0 -38:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:4/0/physics_layer_0/angular_velocity = 0.0 -39:4/0 = 0 -39:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:4/0/physics_layer_0/angular_velocity = 0.0 -40:4/0 = 0 -40:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:4/0/physics_layer_0/angular_velocity = 0.0 -41:4/0 = 0 -41:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:4/0/physics_layer_0/angular_velocity = 0.0 -42:4/0 = 0 -42:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:4/0/physics_layer_0/angular_velocity = 0.0 -43:4/0 = 0 -43:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:4/0/physics_layer_0/angular_velocity = 0.0 -44:4/0 = 0 -44:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:4/0/physics_layer_0/angular_velocity = 0.0 -45:4/0 = 0 -45:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:4/0/physics_layer_0/angular_velocity = 0.0 -46:4/0 = 0 -46:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:4/0/physics_layer_0/angular_velocity = 0.0 -47:4/0 = 0 -47:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:4/0/physics_layer_0/angular_velocity = 0.0 -48:4/0 = 0 -48:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:4/0/physics_layer_0/angular_velocity = 0.0 -0:5/0 = 0 -0:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:5/0/physics_layer_0/angular_velocity = 0.0 -1:5/0 = 0 -1:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:5/0/physics_layer_0/angular_velocity = 0.0 -2:5/0 = 0 -2:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:5/0/physics_layer_0/angular_velocity = 0.0 -3:5/0 = 0 -3:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:5/0/physics_layer_0/angular_velocity = 0.0 -4:5/0 = 0 -4:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:5/0/physics_layer_0/angular_velocity = 0.0 -5:5/0 = 0 -5:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:5/0/physics_layer_0/angular_velocity = 0.0 -6:5/0 = 0 -6:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:5/0/physics_layer_0/angular_velocity = 0.0 -7:5/0 = 0 -7:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:5/0/physics_layer_0/angular_velocity = 0.0 -8:5/0 = 0 -8:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:5/0/physics_layer_0/angular_velocity = 0.0 -9:5/0 = 0 -9:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:5/0/physics_layer_0/angular_velocity = 0.0 -10:5/0 = 0 -10:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:5/0/physics_layer_0/angular_velocity = 0.0 -11:5/0 = 0 -11:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:5/0/physics_layer_0/angular_velocity = 0.0 -12:5/0 = 0 -12:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:5/0/physics_layer_0/angular_velocity = 0.0 -13:5/0 = 0 -13:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:5/0/physics_layer_0/angular_velocity = 0.0 -14:5/0 = 0 -14:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:5/0/physics_layer_0/angular_velocity = 0.0 -15:5/0 = 0 -15:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:5/0/physics_layer_0/angular_velocity = 0.0 -16:5/0 = 0 -16:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:5/0/physics_layer_0/angular_velocity = 0.0 -17:5/0 = 0 -17:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:5/0/physics_layer_0/angular_velocity = 0.0 -18:5/0 = 0 -18:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:5/0/physics_layer_0/angular_velocity = 0.0 -19:5/0 = 0 -19:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:5/0/physics_layer_0/angular_velocity = 0.0 -20:5/0 = 0 -20:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:5/0/physics_layer_0/angular_velocity = 0.0 -21:5/0 = 0 -21:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:5/0/physics_layer_0/angular_velocity = 0.0 -22:5/0 = 0 -22:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:5/0/physics_layer_0/angular_velocity = 0.0 -23:5/0 = 0 -23:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:5/0/physics_layer_0/angular_velocity = 0.0 -24:5/0 = 0 -24:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:5/0/physics_layer_0/angular_velocity = 0.0 -25:5/0 = 0 -25:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:5/0/physics_layer_0/angular_velocity = 0.0 -26:5/0 = 0 -26:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:5/0/physics_layer_0/angular_velocity = 0.0 -27:5/0 = 0 -27:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:5/0/physics_layer_0/angular_velocity = 0.0 -28:5/0 = 0 -28:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:5/0/physics_layer_0/angular_velocity = 0.0 -29:5/0 = 0 -29:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:5/0/physics_layer_0/angular_velocity = 0.0 -30:5/0 = 0 -30:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:5/0/physics_layer_0/angular_velocity = 0.0 -31:5/0 = 0 -31:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:5/0/physics_layer_0/angular_velocity = 0.0 -32:5/0 = 0 -32:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:5/0/physics_layer_0/angular_velocity = 0.0 -33:5/0 = 0 -33:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:5/0/physics_layer_0/angular_velocity = 0.0 -34:5/0 = 0 -34:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:5/0/physics_layer_0/angular_velocity = 0.0 -35:5/0 = 0 -35:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:5/0/physics_layer_0/angular_velocity = 0.0 -36:5/0 = 0 -36:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:5/0/physics_layer_0/angular_velocity = 0.0 -37:5/0 = 0 -37:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:5/0/physics_layer_0/angular_velocity = 0.0 -38:5/0 = 0 -38:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:5/0/physics_layer_0/angular_velocity = 0.0 -39:5/0 = 0 -39:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:5/0/physics_layer_0/angular_velocity = 0.0 -40:5/0 = 0 -40:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:5/0/physics_layer_0/angular_velocity = 0.0 -41:5/0 = 0 -41:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:5/0/physics_layer_0/angular_velocity = 0.0 -42:5/0 = 0 -42:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:5/0/physics_layer_0/angular_velocity = 0.0 -43:5/0 = 0 -43:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:5/0/physics_layer_0/angular_velocity = 0.0 -44:5/0 = 0 -44:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:5/0/physics_layer_0/angular_velocity = 0.0 -45:5/0 = 0 -45:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:5/0/physics_layer_0/angular_velocity = 0.0 -46:5/0 = 0 -46:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:5/0/physics_layer_0/angular_velocity = 0.0 -47:5/0 = 0 -47:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:5/0/physics_layer_0/angular_velocity = 0.0 -48:5/0 = 0 -48:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:5/0/physics_layer_0/angular_velocity = 0.0 -0:6/0 = 0 -0:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:6/0/physics_layer_0/angular_velocity = 0.0 -1:6/0 = 0 -1:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:6/0/physics_layer_0/angular_velocity = 0.0 -2:6/0 = 0 -2:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:6/0/physics_layer_0/angular_velocity = 0.0 -3:6/0 = 0 -3:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:6/0/physics_layer_0/angular_velocity = 0.0 -4:6/0 = 0 -4:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:6/0/physics_layer_0/angular_velocity = 0.0 -5:6/0 = 0 -5:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:6/0/physics_layer_0/angular_velocity = 0.0 -6:6/0 = 0 -6:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:6/0/physics_layer_0/angular_velocity = 0.0 -7:6/0 = 0 -7:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:6/0/physics_layer_0/angular_velocity = 0.0 -8:6/0 = 0 -8:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:6/0/physics_layer_0/angular_velocity = 0.0 -9:6/0 = 0 -9:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:6/0/physics_layer_0/angular_velocity = 0.0 -10:6/0 = 0 -10:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:6/0/physics_layer_0/angular_velocity = 0.0 -11:6/0 = 0 -11:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:6/0/physics_layer_0/angular_velocity = 0.0 -12:6/0 = 0 -12:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:6/0/physics_layer_0/angular_velocity = 0.0 -13:6/0 = 0 -13:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:6/0/physics_layer_0/angular_velocity = 0.0 -14:6/0 = 0 -14:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:6/0/physics_layer_0/angular_velocity = 0.0 -15:6/0 = 0 -15:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:6/0/physics_layer_0/angular_velocity = 0.0 -16:6/0 = 0 -16:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:6/0/physics_layer_0/angular_velocity = 0.0 -17:6/0 = 0 -17:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:6/0/physics_layer_0/angular_velocity = 0.0 -18:6/0 = 0 -18:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:6/0/physics_layer_0/angular_velocity = 0.0 -19:6/0 = 0 -19:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:6/0/physics_layer_0/angular_velocity = 0.0 -20:6/0 = 0 -20:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:6/0/physics_layer_0/angular_velocity = 0.0 -21:6/0 = 0 -21:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:6/0/physics_layer_0/angular_velocity = 0.0 -22:6/0 = 0 -22:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:6/0/physics_layer_0/angular_velocity = 0.0 -23:6/0 = 0 -23:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:6/0/physics_layer_0/angular_velocity = 0.0 -24:6/0 = 0 -24:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:6/0/physics_layer_0/angular_velocity = 0.0 -25:6/0 = 0 -25:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:6/0/physics_layer_0/angular_velocity = 0.0 -26:6/0 = 0 -26:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:6/0/physics_layer_0/angular_velocity = 0.0 -27:6/0 = 0 -27:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:6/0/physics_layer_0/angular_velocity = 0.0 -28:6/0 = 0 -28:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:6/0/physics_layer_0/angular_velocity = 0.0 -29:6/0 = 0 -29:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:6/0/physics_layer_0/angular_velocity = 0.0 -30:6/0 = 0 -30:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:6/0/physics_layer_0/angular_velocity = 0.0 -31:6/0 = 0 -31:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:6/0/physics_layer_0/angular_velocity = 0.0 -32:6/0 = 0 -32:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:6/0/physics_layer_0/angular_velocity = 0.0 -33:6/0 = 0 -33:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:6/0/physics_layer_0/angular_velocity = 0.0 -34:6/0 = 0 -34:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:6/0/physics_layer_0/angular_velocity = 0.0 -35:6/0 = 0 -35:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:6/0/physics_layer_0/angular_velocity = 0.0 -36:6/0 = 0 -36:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:6/0/physics_layer_0/angular_velocity = 0.0 -37:6/0 = 0 -37:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:6/0/physics_layer_0/angular_velocity = 0.0 -38:6/0 = 0 -38:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:6/0/physics_layer_0/angular_velocity = 0.0 -39:6/0 = 0 -39:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:6/0/physics_layer_0/angular_velocity = 0.0 -40:6/0 = 0 -40:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:6/0/physics_layer_0/angular_velocity = 0.0 -41:6/0 = 0 -41:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:6/0/physics_layer_0/angular_velocity = 0.0 -42:6/0 = 0 -42:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:6/0/physics_layer_0/angular_velocity = 0.0 -43:6/0 = 0 -43:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:6/0/physics_layer_0/angular_velocity = 0.0 -44:6/0 = 0 -44:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:6/0/physics_layer_0/angular_velocity = 0.0 -45:6/0 = 0 -45:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:6/0/physics_layer_0/angular_velocity = 0.0 -46:6/0 = 0 -46:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:6/0/physics_layer_0/angular_velocity = 0.0 -47:6/0 = 0 -47:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:6/0/physics_layer_0/angular_velocity = 0.0 -48:6/0 = 0 -48:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:6/0/physics_layer_0/angular_velocity = 0.0 -0:7/0 = 0 -0:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:7/0/physics_layer_0/angular_velocity = 0.0 -1:7/0 = 0 -1:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:7/0/physics_layer_0/angular_velocity = 0.0 -2:7/0 = 0 -2:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:7/0/physics_layer_0/angular_velocity = 0.0 -3:7/0 = 0 -3:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:7/0/physics_layer_0/angular_velocity = 0.0 -4:7/0 = 0 -4:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:7/0/physics_layer_0/angular_velocity = 0.0 -5:7/0 = 0 -5:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:7/0/physics_layer_0/angular_velocity = 0.0 -6:7/0 = 0 -6:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:7/0/physics_layer_0/angular_velocity = 0.0 -7:7/0 = 0 -7:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:7/0/physics_layer_0/angular_velocity = 0.0 -8:7/0 = 0 -8:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:7/0/physics_layer_0/angular_velocity = 0.0 -9:7/0 = 0 -9:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:7/0/physics_layer_0/angular_velocity = 0.0 -10:7/0 = 0 -10:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:7/0/physics_layer_0/angular_velocity = 0.0 -11:7/0 = 0 -11:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:7/0/physics_layer_0/angular_velocity = 0.0 -12:7/0 = 0 -12:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:7/0/physics_layer_0/angular_velocity = 0.0 -13:7/0 = 0 -13:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:7/0/physics_layer_0/angular_velocity = 0.0 -14:7/0 = 0 -14:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:7/0/physics_layer_0/angular_velocity = 0.0 -15:7/0 = 0 -15:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:7/0/physics_layer_0/angular_velocity = 0.0 -16:7/0 = 0 -16:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:7/0/physics_layer_0/angular_velocity = 0.0 -17:7/0 = 0 -17:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:7/0/physics_layer_0/angular_velocity = 0.0 -18:7/0 = 0 -18:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:7/0/physics_layer_0/angular_velocity = 0.0 -19:7/0 = 0 -19:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:7/0/physics_layer_0/angular_velocity = 0.0 -20:7/0 = 0 -20:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:7/0/physics_layer_0/angular_velocity = 0.0 -21:7/0 = 0 -21:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:7/0/physics_layer_0/angular_velocity = 0.0 -22:7/0 = 0 -22:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:7/0/physics_layer_0/angular_velocity = 0.0 -23:7/0 = 0 -23:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:7/0/physics_layer_0/angular_velocity = 0.0 -24:7/0 = 0 -24:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:7/0/physics_layer_0/angular_velocity = 0.0 -25:7/0 = 0 -25:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:7/0/physics_layer_0/angular_velocity = 0.0 -26:7/0 = 0 -26:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:7/0/physics_layer_0/angular_velocity = 0.0 -27:7/0 = 0 -27:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:7/0/physics_layer_0/angular_velocity = 0.0 -28:7/0 = 0 -28:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:7/0/physics_layer_0/angular_velocity = 0.0 -29:7/0 = 0 -29:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:7/0/physics_layer_0/angular_velocity = 0.0 -30:7/0 = 0 -30:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:7/0/physics_layer_0/angular_velocity = 0.0 -31:7/0 = 0 -31:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:7/0/physics_layer_0/angular_velocity = 0.0 -32:7/0 = 0 -32:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:7/0/physics_layer_0/angular_velocity = 0.0 -33:7/0 = 0 -33:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:7/0/physics_layer_0/angular_velocity = 0.0 -34:7/0 = 0 -34:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:7/0/physics_layer_0/angular_velocity = 0.0 -35:7/0 = 0 -35:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:7/0/physics_layer_0/angular_velocity = 0.0 -36:7/0 = 0 -36:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:7/0/physics_layer_0/angular_velocity = 0.0 -37:7/0 = 0 -37:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:7/0/physics_layer_0/angular_velocity = 0.0 -38:7/0 = 0 -38:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:7/0/physics_layer_0/angular_velocity = 0.0 -39:7/0 = 0 -39:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:7/0/physics_layer_0/angular_velocity = 0.0 -40:7/0 = 0 -40:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:7/0/physics_layer_0/angular_velocity = 0.0 -41:7/0 = 0 -41:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:7/0/physics_layer_0/angular_velocity = 0.0 -42:7/0 = 0 -42:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:7/0/physics_layer_0/angular_velocity = 0.0 -43:7/0 = 0 -43:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:7/0/physics_layer_0/angular_velocity = 0.0 -44:7/0 = 0 -44:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:7/0/physics_layer_0/angular_velocity = 0.0 -45:7/0 = 0 -45:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:7/0/physics_layer_0/angular_velocity = 0.0 -46:7/0 = 0 -46:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:7/0/physics_layer_0/angular_velocity = 0.0 -47:7/0 = 0 -47:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:7/0/physics_layer_0/angular_velocity = 0.0 -48:7/0 = 0 -48:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:7/0/physics_layer_0/angular_velocity = 0.0 -0:8/0 = 0 -0:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:8/0/physics_layer_0/angular_velocity = 0.0 -1:8/0 = 0 -1:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:8/0/physics_layer_0/angular_velocity = 0.0 -2:8/0 = 0 -2:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:8/0/physics_layer_0/angular_velocity = 0.0 -3:8/0 = 0 -3:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:8/0/physics_layer_0/angular_velocity = 0.0 -4:8/0 = 0 -4:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:8/0/physics_layer_0/angular_velocity = 0.0 -5:8/0 = 0 -5:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:8/0/physics_layer_0/angular_velocity = 0.0 -6:8/0 = 0 -6:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:8/0/physics_layer_0/angular_velocity = 0.0 -7:8/0 = 0 -7:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:8/0/physics_layer_0/angular_velocity = 0.0 -8:8/0 = 0 -8:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:8/0/physics_layer_0/angular_velocity = 0.0 -9:8/0 = 0 -9:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:8/0/physics_layer_0/angular_velocity = 0.0 -10:8/0 = 0 -10:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:8/0/physics_layer_0/angular_velocity = 0.0 -11:8/0 = 0 -11:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:8/0/physics_layer_0/angular_velocity = 0.0 -12:8/0 = 0 -12:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:8/0/physics_layer_0/angular_velocity = 0.0 -13:8/0 = 0 -13:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:8/0/physics_layer_0/angular_velocity = 0.0 -14:8/0 = 0 -14:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:8/0/physics_layer_0/angular_velocity = 0.0 -15:8/0 = 0 -15:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:8/0/physics_layer_0/angular_velocity = 0.0 -16:8/0 = 0 -16:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:8/0/physics_layer_0/angular_velocity = 0.0 -17:8/0 = 0 -17:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:8/0/physics_layer_0/angular_velocity = 0.0 -18:8/0 = 0 -18:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:8/0/physics_layer_0/angular_velocity = 0.0 -19:8/0 = 0 -19:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:8/0/physics_layer_0/angular_velocity = 0.0 -20:8/0 = 0 -20:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:8/0/physics_layer_0/angular_velocity = 0.0 -21:8/0 = 0 -21:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:8/0/physics_layer_0/angular_velocity = 0.0 -22:8/0 = 0 -22:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:8/0/physics_layer_0/angular_velocity = 0.0 -23:8/0 = 0 -23:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:8/0/physics_layer_0/angular_velocity = 0.0 -24:8/0 = 0 -24:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:8/0/physics_layer_0/angular_velocity = 0.0 -25:8/0 = 0 -25:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:8/0/physics_layer_0/angular_velocity = 0.0 -26:8/0 = 0 -26:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:8/0/physics_layer_0/angular_velocity = 0.0 -27:8/0 = 0 -27:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:8/0/physics_layer_0/angular_velocity = 0.0 -28:8/0 = 0 -28:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:8/0/physics_layer_0/angular_velocity = 0.0 -29:8/0 = 0 -29:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:8/0/physics_layer_0/angular_velocity = 0.0 -30:8/0 = 0 -30:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:8/0/physics_layer_0/angular_velocity = 0.0 -31:8/0 = 0 -31:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:8/0/physics_layer_0/angular_velocity = 0.0 -32:8/0 = 0 -32:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:8/0/physics_layer_0/angular_velocity = 0.0 -33:8/0 = 0 -33:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:8/0/physics_layer_0/angular_velocity = 0.0 -34:8/0 = 0 -34:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:8/0/physics_layer_0/angular_velocity = 0.0 -35:8/0 = 0 -35:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:8/0/physics_layer_0/angular_velocity = 0.0 -36:8/0 = 0 -36:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:8/0/physics_layer_0/angular_velocity = 0.0 -37:8/0 = 0 -37:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:8/0/physics_layer_0/angular_velocity = 0.0 -38:8/0 = 0 -38:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:8/0/physics_layer_0/angular_velocity = 0.0 -39:8/0 = 0 -39:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:8/0/physics_layer_0/angular_velocity = 0.0 -40:8/0 = 0 -40:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:8/0/physics_layer_0/angular_velocity = 0.0 -41:8/0 = 0 -41:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:8/0/physics_layer_0/angular_velocity = 0.0 -42:8/0 = 0 -42:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:8/0/physics_layer_0/angular_velocity = 0.0 -43:8/0 = 0 -43:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:8/0/physics_layer_0/angular_velocity = 0.0 -44:8/0 = 0 -44:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:8/0/physics_layer_0/angular_velocity = 0.0 -45:8/0 = 0 -45:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:8/0/physics_layer_0/angular_velocity = 0.0 -46:8/0 = 0 -46:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:8/0/physics_layer_0/angular_velocity = 0.0 -47:8/0 = 0 -47:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:8/0/physics_layer_0/angular_velocity = 0.0 -48:8/0 = 0 -48:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:8/0/physics_layer_0/angular_velocity = 0.0 -0:9/0 = 0 -0:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:9/0/physics_layer_0/angular_velocity = 0.0 -1:9/0 = 0 -1:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:9/0/physics_layer_0/angular_velocity = 0.0 -2:9/0 = 0 -2:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:9/0/physics_layer_0/angular_velocity = 0.0 -3:9/0 = 0 -3:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:9/0/physics_layer_0/angular_velocity = 0.0 -4:9/0 = 0 -4:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:9/0/physics_layer_0/angular_velocity = 0.0 -5:9/0 = 0 -5:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:9/0/physics_layer_0/angular_velocity = 0.0 -6:9/0 = 0 -6:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:9/0/physics_layer_0/angular_velocity = 0.0 -7:9/0 = 0 -7:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:9/0/physics_layer_0/angular_velocity = 0.0 -8:9/0 = 0 -8:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:9/0/physics_layer_0/angular_velocity = 0.0 -9:9/0 = 0 -9:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:9/0/physics_layer_0/angular_velocity = 0.0 -10:9/0 = 0 -10:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:9/0/physics_layer_0/angular_velocity = 0.0 -11:9/0 = 0 -11:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:9/0/physics_layer_0/angular_velocity = 0.0 -12:9/0 = 0 -12:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:9/0/physics_layer_0/angular_velocity = 0.0 -13:9/0 = 0 -13:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:9/0/physics_layer_0/angular_velocity = 0.0 -14:9/0 = 0 -14:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:9/0/physics_layer_0/angular_velocity = 0.0 -15:9/0 = 0 -15:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:9/0/physics_layer_0/angular_velocity = 0.0 -16:9/0 = 0 -16:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:9/0/physics_layer_0/angular_velocity = 0.0 -17:9/0 = 0 -17:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:9/0/physics_layer_0/angular_velocity = 0.0 -18:9/0 = 0 -18:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:9/0/physics_layer_0/angular_velocity = 0.0 -19:9/0 = 0 -19:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:9/0/physics_layer_0/angular_velocity = 0.0 -20:9/0 = 0 -20:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:9/0/physics_layer_0/angular_velocity = 0.0 -21:9/0 = 0 -21:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:9/0/physics_layer_0/angular_velocity = 0.0 -22:9/0 = 0 -22:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:9/0/physics_layer_0/angular_velocity = 0.0 -23:9/0 = 0 -23:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:9/0/physics_layer_0/angular_velocity = 0.0 -24:9/0 = 0 -24:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:9/0/physics_layer_0/angular_velocity = 0.0 -25:9/0 = 0 -25:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:9/0/physics_layer_0/angular_velocity = 0.0 -26:9/0 = 0 -26:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:9/0/physics_layer_0/angular_velocity = 0.0 -27:9/0 = 0 -27:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:9/0/physics_layer_0/angular_velocity = 0.0 -28:9/0 = 0 -28:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:9/0/physics_layer_0/angular_velocity = 0.0 -29:9/0 = 0 -29:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:9/0/physics_layer_0/angular_velocity = 0.0 -30:9/0 = 0 -30:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:9/0/physics_layer_0/angular_velocity = 0.0 -31:9/0 = 0 -31:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:9/0/physics_layer_0/angular_velocity = 0.0 -32:9/0 = 0 -32:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:9/0/physics_layer_0/angular_velocity = 0.0 -33:9/0 = 0 -33:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:9/0/physics_layer_0/angular_velocity = 0.0 -34:9/0 = 0 -34:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:9/0/physics_layer_0/angular_velocity = 0.0 -35:9/0 = 0 -35:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:9/0/physics_layer_0/angular_velocity = 0.0 -36:9/0 = 0 -36:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:9/0/physics_layer_0/angular_velocity = 0.0 -37:9/0 = 0 -37:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:9/0/physics_layer_0/angular_velocity = 0.0 -38:9/0 = 0 -38:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:9/0/physics_layer_0/angular_velocity = 0.0 -39:9/0 = 0 -39:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:9/0/physics_layer_0/angular_velocity = 0.0 -40:9/0 = 0 -40:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:9/0/physics_layer_0/angular_velocity = 0.0 -41:9/0 = 0 -41:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:9/0/physics_layer_0/angular_velocity = 0.0 -42:9/0 = 0 -42:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:9/0/physics_layer_0/angular_velocity = 0.0 -43:9/0 = 0 -43:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:9/0/physics_layer_0/angular_velocity = 0.0 -44:9/0 = 0 -44:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:9/0/physics_layer_0/angular_velocity = 0.0 -45:9/0 = 0 -45:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:9/0/physics_layer_0/angular_velocity = 0.0 -46:9/0 = 0 -46:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:9/0/physics_layer_0/angular_velocity = 0.0 -47:9/0 = 0 -47:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:9/0/physics_layer_0/angular_velocity = 0.0 -48:9/0 = 0 -48:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:9/0/physics_layer_0/angular_velocity = 0.0 -0:10/0 = 0 -0:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:10/0/physics_layer_0/angular_velocity = 0.0 -1:10/0 = 0 -1:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:10/0/physics_layer_0/angular_velocity = 0.0 -2:10/0 = 0 -2:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:10/0/physics_layer_0/angular_velocity = 0.0 -3:10/0 = 0 -3:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:10/0/physics_layer_0/angular_velocity = 0.0 -4:10/0 = 0 -4:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:10/0/physics_layer_0/angular_velocity = 0.0 -5:10/0 = 0 -5:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:10/0/physics_layer_0/angular_velocity = 0.0 -6:10/0 = 0 -6:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:10/0/physics_layer_0/angular_velocity = 0.0 -7:10/0 = 0 -7:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:10/0/physics_layer_0/angular_velocity = 0.0 -8:10/0 = 0 -8:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:10/0/physics_layer_0/angular_velocity = 0.0 -9:10/0 = 0 -9:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:10/0/physics_layer_0/angular_velocity = 0.0 -10:10/0 = 0 -10:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:10/0/physics_layer_0/angular_velocity = 0.0 -11:10/0 = 0 -11:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:10/0/physics_layer_0/angular_velocity = 0.0 -12:10/0 = 0 -12:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:10/0/physics_layer_0/angular_velocity = 0.0 -13:10/0 = 0 -13:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:10/0/physics_layer_0/angular_velocity = 0.0 -14:10/0 = 0 -14:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:10/0/physics_layer_0/angular_velocity = 0.0 -15:10/0 = 0 -15:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:10/0/physics_layer_0/angular_velocity = 0.0 -16:10/0 = 0 -16:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:10/0/physics_layer_0/angular_velocity = 0.0 -17:10/0 = 0 -17:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:10/0/physics_layer_0/angular_velocity = 0.0 -18:10/0 = 0 -18:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:10/0/physics_layer_0/angular_velocity = 0.0 -19:10/0 = 0 -19:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:10/0/physics_layer_0/angular_velocity = 0.0 -20:10/0 = 0 -20:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:10/0/physics_layer_0/angular_velocity = 0.0 -21:10/0 = 0 -21:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:10/0/physics_layer_0/angular_velocity = 0.0 -22:10/0 = 0 -22:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:10/0/physics_layer_0/angular_velocity = 0.0 -23:10/0 = 0 -23:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:10/0/physics_layer_0/angular_velocity = 0.0 -24:10/0 = 0 -24:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:10/0/physics_layer_0/angular_velocity = 0.0 -25:10/0 = 0 -25:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:10/0/physics_layer_0/angular_velocity = 0.0 -26:10/0 = 0 -26:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:10/0/physics_layer_0/angular_velocity = 0.0 -27:10/0 = 0 -27:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:10/0/physics_layer_0/angular_velocity = 0.0 -28:10/0 = 0 -28:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:10/0/physics_layer_0/angular_velocity = 0.0 -29:10/0 = 0 -29:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:10/0/physics_layer_0/angular_velocity = 0.0 -30:10/0 = 0 -30:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:10/0/physics_layer_0/angular_velocity = 0.0 -31:10/0 = 0 -31:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:10/0/physics_layer_0/angular_velocity = 0.0 -32:10/0 = 0 -32:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:10/0/physics_layer_0/angular_velocity = 0.0 -33:10/0 = 0 -33:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:10/0/physics_layer_0/angular_velocity = 0.0 -34:10/0 = 0 -34:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:10/0/physics_layer_0/angular_velocity = 0.0 -35:10/0 = 0 -35:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:10/0/physics_layer_0/angular_velocity = 0.0 -36:10/0 = 0 -36:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:10/0/physics_layer_0/angular_velocity = 0.0 -37:10/0 = 0 -37:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:10/0/physics_layer_0/angular_velocity = 0.0 -38:10/0 = 0 -38:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:10/0/physics_layer_0/angular_velocity = 0.0 -39:10/0 = 0 -39:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:10/0/physics_layer_0/angular_velocity = 0.0 -40:10/0 = 0 -40:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:10/0/physics_layer_0/angular_velocity = 0.0 -41:10/0 = 0 -41:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:10/0/physics_layer_0/angular_velocity = 0.0 -42:10/0 = 0 -42:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:10/0/physics_layer_0/angular_velocity = 0.0 -43:10/0 = 0 -43:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:10/0/physics_layer_0/angular_velocity = 0.0 -44:10/0 = 0 -44:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:10/0/physics_layer_0/angular_velocity = 0.0 -45:10/0 = 0 -45:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:10/0/physics_layer_0/angular_velocity = 0.0 -46:10/0 = 0 -46:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:10/0/physics_layer_0/angular_velocity = 0.0 -47:10/0 = 0 -47:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:10/0/physics_layer_0/angular_velocity = 0.0 -48:10/0 = 0 -48:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:10/0/physics_layer_0/angular_velocity = 0.0 -0:11/0 = 0 -0:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:11/0/physics_layer_0/angular_velocity = 0.0 -1:11/0 = 0 -1:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:11/0/physics_layer_0/angular_velocity = 0.0 -2:11/0 = 0 -2:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:11/0/physics_layer_0/angular_velocity = 0.0 -3:11/0 = 0 -3:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:11/0/physics_layer_0/angular_velocity = 0.0 -4:11/0 = 0 -4:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:11/0/physics_layer_0/angular_velocity = 0.0 -5:11/0 = 0 -5:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:11/0/physics_layer_0/angular_velocity = 0.0 -6:11/0 = 0 -6:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:11/0/physics_layer_0/angular_velocity = 0.0 -7:11/0 = 0 -7:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:11/0/physics_layer_0/angular_velocity = 0.0 -8:11/0 = 0 -8:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:11/0/physics_layer_0/angular_velocity = 0.0 -9:11/0 = 0 -9:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:11/0/physics_layer_0/angular_velocity = 0.0 -10:11/0 = 0 -10:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:11/0/physics_layer_0/angular_velocity = 0.0 -11:11/0 = 0 -11:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:11/0/physics_layer_0/angular_velocity = 0.0 -12:11/0 = 0 -12:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:11/0/physics_layer_0/angular_velocity = 0.0 -13:11/0 = 0 -13:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:11/0/physics_layer_0/angular_velocity = 0.0 -14:11/0 = 0 -14:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:11/0/physics_layer_0/angular_velocity = 0.0 -15:11/0 = 0 -15:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:11/0/physics_layer_0/angular_velocity = 0.0 -16:11/0 = 0 -16:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:11/0/physics_layer_0/angular_velocity = 0.0 -17:11/0 = 0 -17:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:11/0/physics_layer_0/angular_velocity = 0.0 -18:11/0 = 0 -18:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:11/0/physics_layer_0/angular_velocity = 0.0 -19:11/0 = 0 -19:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:11/0/physics_layer_0/angular_velocity = 0.0 -20:11/0 = 0 -20:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:11/0/physics_layer_0/angular_velocity = 0.0 -21:11/0 = 0 -21:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:11/0/physics_layer_0/angular_velocity = 0.0 -22:11/0 = 0 -22:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:11/0/physics_layer_0/angular_velocity = 0.0 -23:11/0 = 0 -23:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:11/0/physics_layer_0/angular_velocity = 0.0 -24:11/0 = 0 -24:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:11/0/physics_layer_0/angular_velocity = 0.0 -25:11/0 = 0 -25:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:11/0/physics_layer_0/angular_velocity = 0.0 -26:11/0 = 0 -26:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:11/0/physics_layer_0/angular_velocity = 0.0 -27:11/0 = 0 -27:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:11/0/physics_layer_0/angular_velocity = 0.0 -28:11/0 = 0 -28:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:11/0/physics_layer_0/angular_velocity = 0.0 -29:11/0 = 0 -29:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:11/0/physics_layer_0/angular_velocity = 0.0 -30:11/0 = 0 -30:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:11/0/physics_layer_0/angular_velocity = 0.0 -31:11/0 = 0 -31:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:11/0/physics_layer_0/angular_velocity = 0.0 -32:11/0 = 0 -32:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:11/0/physics_layer_0/angular_velocity = 0.0 -33:11/0 = 0 -33:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:11/0/physics_layer_0/angular_velocity = 0.0 -34:11/0 = 0 -34:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:11/0/physics_layer_0/angular_velocity = 0.0 -35:11/0 = 0 -35:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:11/0/physics_layer_0/angular_velocity = 0.0 -36:11/0 = 0 -36:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:11/0/physics_layer_0/angular_velocity = 0.0 -37:11/0 = 0 -37:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:11/0/physics_layer_0/angular_velocity = 0.0 -38:11/0 = 0 -38:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:11/0/physics_layer_0/angular_velocity = 0.0 -39:11/0 = 0 -39:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:11/0/physics_layer_0/angular_velocity = 0.0 -40:11/0 = 0 -40:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:11/0/physics_layer_0/angular_velocity = 0.0 -41:11/0 = 0 -41:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:11/0/physics_layer_0/angular_velocity = 0.0 -42:11/0 = 0 -42:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:11/0/physics_layer_0/angular_velocity = 0.0 -43:11/0 = 0 -43:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:11/0/physics_layer_0/angular_velocity = 0.0 -44:11/0 = 0 -44:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:11/0/physics_layer_0/angular_velocity = 0.0 -45:11/0 = 0 -45:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:11/0/physics_layer_0/angular_velocity = 0.0 -46:11/0 = 0 -46:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:11/0/physics_layer_0/angular_velocity = 0.0 -47:11/0 = 0 -47:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:11/0/physics_layer_0/angular_velocity = 0.0 -48:11/0 = 0 -48:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:11/0/physics_layer_0/angular_velocity = 0.0 -0:12/0 = 0 -0:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:12/0/physics_layer_0/angular_velocity = 0.0 -1:12/0 = 0 -1:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:12/0/physics_layer_0/angular_velocity = 0.0 -2:12/0 = 0 -2:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:12/0/physics_layer_0/angular_velocity = 0.0 -3:12/0 = 0 -3:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:12/0/physics_layer_0/angular_velocity = 0.0 -4:12/0 = 0 -4:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:12/0/physics_layer_0/angular_velocity = 0.0 -5:12/0 = 0 -5:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:12/0/physics_layer_0/angular_velocity = 0.0 -6:12/0 = 0 -6:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:12/0/physics_layer_0/angular_velocity = 0.0 -7:12/0 = 0 -7:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:12/0/physics_layer_0/angular_velocity = 0.0 -8:12/0 = 0 -8:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:12/0/physics_layer_0/angular_velocity = 0.0 -9:12/0 = 0 -9:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:12/0/physics_layer_0/angular_velocity = 0.0 -10:12/0 = 0 -10:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:12/0/physics_layer_0/angular_velocity = 0.0 -11:12/0 = 0 -11:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:12/0/physics_layer_0/angular_velocity = 0.0 -12:12/0 = 0 -12:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:12/0/physics_layer_0/angular_velocity = 0.0 -13:12/0 = 0 -13:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:12/0/physics_layer_0/angular_velocity = 0.0 -14:12/0 = 0 -14:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:12/0/physics_layer_0/angular_velocity = 0.0 -15:12/0 = 0 -15:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:12/0/physics_layer_0/angular_velocity = 0.0 -16:12/0 = 0 -16:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:12/0/physics_layer_0/angular_velocity = 0.0 -17:12/0 = 0 -17:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:12/0/physics_layer_0/angular_velocity = 0.0 -18:12/0 = 0 -18:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:12/0/physics_layer_0/angular_velocity = 0.0 -19:12/0 = 0 -19:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:12/0/physics_layer_0/angular_velocity = 0.0 -20:12/0 = 0 -20:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:12/0/physics_layer_0/angular_velocity = 0.0 -21:12/0 = 0 -21:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:12/0/physics_layer_0/angular_velocity = 0.0 -22:12/0 = 0 -22:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:12/0/physics_layer_0/angular_velocity = 0.0 -23:12/0 = 0 -23:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:12/0/physics_layer_0/angular_velocity = 0.0 -24:12/0 = 0 -24:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:12/0/physics_layer_0/angular_velocity = 0.0 -25:12/0 = 0 -25:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:12/0/physics_layer_0/angular_velocity = 0.0 -26:12/0 = 0 -26:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:12/0/physics_layer_0/angular_velocity = 0.0 -27:12/0 = 0 -27:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:12/0/physics_layer_0/angular_velocity = 0.0 -28:12/0 = 0 -28:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:12/0/physics_layer_0/angular_velocity = 0.0 -29:12/0 = 0 -29:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:12/0/physics_layer_0/angular_velocity = 0.0 -30:12/0 = 0 -30:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:12/0/physics_layer_0/angular_velocity = 0.0 -31:12/0 = 0 -31:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:12/0/physics_layer_0/angular_velocity = 0.0 -32:12/0 = 0 -32:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:12/0/physics_layer_0/angular_velocity = 0.0 -33:12/0 = 0 -33:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:12/0/physics_layer_0/angular_velocity = 0.0 -34:12/0 = 0 -34:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:12/0/physics_layer_0/angular_velocity = 0.0 -35:12/0 = 0 -35:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:12/0/physics_layer_0/angular_velocity = 0.0 -36:12/0 = 0 -36:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:12/0/physics_layer_0/angular_velocity = 0.0 -37:12/0 = 0 -37:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:12/0/physics_layer_0/angular_velocity = 0.0 -38:12/0 = 0 -38:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:12/0/physics_layer_0/angular_velocity = 0.0 -39:12/0 = 0 -39:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:12/0/physics_layer_0/angular_velocity = 0.0 -40:12/0 = 0 -40:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:12/0/physics_layer_0/angular_velocity = 0.0 -41:12/0 = 0 -41:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:12/0/physics_layer_0/angular_velocity = 0.0 -42:12/0 = 0 -42:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:12/0/physics_layer_0/angular_velocity = 0.0 -43:12/0 = 0 -43:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:12/0/physics_layer_0/angular_velocity = 0.0 -44:12/0 = 0 -44:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:12/0/physics_layer_0/angular_velocity = 0.0 -45:12/0 = 0 -45:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:12/0/physics_layer_0/angular_velocity = 0.0 -46:12/0 = 0 -46:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:12/0/physics_layer_0/angular_velocity = 0.0 -47:12/0 = 0 -47:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:12/0/physics_layer_0/angular_velocity = 0.0 -48:12/0 = 0 -48:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:12/0/physics_layer_0/angular_velocity = 0.0 -0:13/0 = 0 -0:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:13/0/physics_layer_0/angular_velocity = 0.0 -1:13/0 = 0 -1:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:13/0/physics_layer_0/angular_velocity = 0.0 -2:13/0 = 0 -2:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:13/0/physics_layer_0/angular_velocity = 0.0 -3:13/0 = 0 -3:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:13/0/physics_layer_0/angular_velocity = 0.0 -4:13/0 = 0 -4:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:13/0/physics_layer_0/angular_velocity = 0.0 -5:13/0 = 0 -5:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:13/0/physics_layer_0/angular_velocity = 0.0 -6:13/0 = 0 -6:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:13/0/physics_layer_0/angular_velocity = 0.0 -7:13/0 = 0 -7:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:13/0/physics_layer_0/angular_velocity = 0.0 -8:13/0 = 0 -8:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:13/0/physics_layer_0/angular_velocity = 0.0 -9:13/0 = 0 -9:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:13/0/physics_layer_0/angular_velocity = 0.0 -10:13/0 = 0 -10:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:13/0/physics_layer_0/angular_velocity = 0.0 -11:13/0 = 0 -11:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:13/0/physics_layer_0/angular_velocity = 0.0 -12:13/0 = 0 -12:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:13/0/physics_layer_0/angular_velocity = 0.0 -13:13/0 = 0 -13:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:13/0/physics_layer_0/angular_velocity = 0.0 -14:13/0 = 0 -14:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:13/0/physics_layer_0/angular_velocity = 0.0 -15:13/0 = 0 -15:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:13/0/physics_layer_0/angular_velocity = 0.0 -16:13/0 = 0 -16:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:13/0/physics_layer_0/angular_velocity = 0.0 -17:13/0 = 0 -17:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:13/0/physics_layer_0/angular_velocity = 0.0 -18:13/0 = 0 -18:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:13/0/physics_layer_0/angular_velocity = 0.0 -19:13/0 = 0 -19:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:13/0/physics_layer_0/angular_velocity = 0.0 -20:13/0 = 0 -20:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:13/0/physics_layer_0/angular_velocity = 0.0 -21:13/0 = 0 -21:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:13/0/physics_layer_0/angular_velocity = 0.0 -22:13/0 = 0 -22:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:13/0/physics_layer_0/angular_velocity = 0.0 -23:13/0 = 0 -23:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:13/0/physics_layer_0/angular_velocity = 0.0 -24:13/0 = 0 -24:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:13/0/physics_layer_0/angular_velocity = 0.0 -25:13/0 = 0 -25:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:13/0/physics_layer_0/angular_velocity = 0.0 -26:13/0 = 0 -26:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:13/0/physics_layer_0/angular_velocity = 0.0 -27:13/0 = 0 -27:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:13/0/physics_layer_0/angular_velocity = 0.0 -28:13/0 = 0 -28:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:13/0/physics_layer_0/angular_velocity = 0.0 -29:13/0 = 0 -29:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:13/0/physics_layer_0/angular_velocity = 0.0 -30:13/0 = 0 -30:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:13/0/physics_layer_0/angular_velocity = 0.0 -31:13/0 = 0 -31:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:13/0/physics_layer_0/angular_velocity = 0.0 -32:13/0 = 0 -32:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:13/0/physics_layer_0/angular_velocity = 0.0 -33:13/0 = 0 -33:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:13/0/physics_layer_0/angular_velocity = 0.0 -34:13/0 = 0 -34:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:13/0/physics_layer_0/angular_velocity = 0.0 -35:13/0 = 0 -35:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:13/0/physics_layer_0/angular_velocity = 0.0 -36:13/0 = 0 -36:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:13/0/physics_layer_0/angular_velocity = 0.0 -37:13/0 = 0 -37:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:13/0/physics_layer_0/angular_velocity = 0.0 -38:13/0 = 0 -38:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:13/0/physics_layer_0/angular_velocity = 0.0 -39:13/0 = 0 -39:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:13/0/physics_layer_0/angular_velocity = 0.0 -40:13/0 = 0 -40:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:13/0/physics_layer_0/angular_velocity = 0.0 -41:13/0 = 0 -41:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:13/0/physics_layer_0/angular_velocity = 0.0 -42:13/0 = 0 -42:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:13/0/physics_layer_0/angular_velocity = 0.0 -43:13/0 = 0 -43:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:13/0/physics_layer_0/angular_velocity = 0.0 -44:13/0 = 0 -44:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:13/0/physics_layer_0/angular_velocity = 0.0 -45:13/0 = 0 -45:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:13/0/physics_layer_0/angular_velocity = 0.0 -46:13/0 = 0 -46:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:13/0/physics_layer_0/angular_velocity = 0.0 -47:13/0 = 0 -47:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:13/0/physics_layer_0/angular_velocity = 0.0 -48:13/0 = 0 -48:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:13/0/physics_layer_0/angular_velocity = 0.0 -0:14/0 = 0 -0:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:14/0/physics_layer_0/angular_velocity = 0.0 -1:14/0 = 0 -1:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:14/0/physics_layer_0/angular_velocity = 0.0 -2:14/0 = 0 -2:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:14/0/physics_layer_0/angular_velocity = 0.0 -3:14/0 = 0 -3:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:14/0/physics_layer_0/angular_velocity = 0.0 -4:14/0 = 0 -4:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:14/0/physics_layer_0/angular_velocity = 0.0 -5:14/0 = 0 -5:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:14/0/physics_layer_0/angular_velocity = 0.0 -6:14/0 = 0 -6:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:14/0/physics_layer_0/angular_velocity = 0.0 -7:14/0 = 0 -7:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:14/0/physics_layer_0/angular_velocity = 0.0 -8:14/0 = 0 -8:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:14/0/physics_layer_0/angular_velocity = 0.0 -9:14/0 = 0 -9:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:14/0/physics_layer_0/angular_velocity = 0.0 -10:14/0 = 0 -10:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:14/0/physics_layer_0/angular_velocity = 0.0 -11:14/0 = 0 -11:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:14/0/physics_layer_0/angular_velocity = 0.0 -12:14/0 = 0 -12:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:14/0/physics_layer_0/angular_velocity = 0.0 -13:14/0 = 0 -13:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:14/0/physics_layer_0/angular_velocity = 0.0 -14:14/0 = 0 -14:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:14/0/physics_layer_0/angular_velocity = 0.0 -15:14/0 = 0 -15:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:14/0/physics_layer_0/angular_velocity = 0.0 -16:14/0 = 0 -16:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:14/0/physics_layer_0/angular_velocity = 0.0 -17:14/0 = 0 -17:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:14/0/physics_layer_0/angular_velocity = 0.0 -18:14/0 = 0 -18:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:14/0/physics_layer_0/angular_velocity = 0.0 -19:14/0 = 0 -19:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:14/0/physics_layer_0/angular_velocity = 0.0 -20:14/0 = 0 -20:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:14/0/physics_layer_0/angular_velocity = 0.0 -21:14/0 = 0 -21:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:14/0/physics_layer_0/angular_velocity = 0.0 -22:14/0 = 0 -22:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:14/0/physics_layer_0/angular_velocity = 0.0 -23:14/0 = 0 -23:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:14/0/physics_layer_0/angular_velocity = 0.0 -24:14/0 = 0 -24:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:14/0/physics_layer_0/angular_velocity = 0.0 -25:14/0 = 0 -25:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:14/0/physics_layer_0/angular_velocity = 0.0 -26:14/0 = 0 -26:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:14/0/physics_layer_0/angular_velocity = 0.0 -27:14/0 = 0 -27:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:14/0/physics_layer_0/angular_velocity = 0.0 -28:14/0 = 0 -28:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:14/0/physics_layer_0/angular_velocity = 0.0 -29:14/0 = 0 -29:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:14/0/physics_layer_0/angular_velocity = 0.0 -30:14/0 = 0 -30:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:14/0/physics_layer_0/angular_velocity = 0.0 -31:14/0 = 0 -31:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:14/0/physics_layer_0/angular_velocity = 0.0 -32:14/0 = 0 -32:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:14/0/physics_layer_0/angular_velocity = 0.0 -33:14/0 = 0 -33:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:14/0/physics_layer_0/angular_velocity = 0.0 -34:14/0 = 0 -34:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:14/0/physics_layer_0/angular_velocity = 0.0 -35:14/0 = 0 -35:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:14/0/physics_layer_0/angular_velocity = 0.0 -36:14/0 = 0 -36:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:14/0/physics_layer_0/angular_velocity = 0.0 -37:14/0 = 0 -37:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:14/0/physics_layer_0/angular_velocity = 0.0 -38:14/0 = 0 -38:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:14/0/physics_layer_0/angular_velocity = 0.0 -39:14/0 = 0 -39:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:14/0/physics_layer_0/angular_velocity = 0.0 -40:14/0 = 0 -40:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:14/0/physics_layer_0/angular_velocity = 0.0 -41:14/0 = 0 -41:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:14/0/physics_layer_0/angular_velocity = 0.0 -42:14/0 = 0 -42:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:14/0/physics_layer_0/angular_velocity = 0.0 -43:14/0 = 0 -43:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:14/0/physics_layer_0/angular_velocity = 0.0 -44:14/0 = 0 -44:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:14/0/physics_layer_0/angular_velocity = 0.0 -45:14/0 = 0 -45:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:14/0/physics_layer_0/angular_velocity = 0.0 -46:14/0 = 0 -46:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:14/0/physics_layer_0/angular_velocity = 0.0 -47:14/0 = 0 -47:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:14/0/physics_layer_0/angular_velocity = 0.0 -48:14/0 = 0 -48:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:14/0/physics_layer_0/angular_velocity = 0.0 -0:15/0 = 0 -0:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:15/0/physics_layer_0/angular_velocity = 0.0 -1:15/0 = 0 -1:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:15/0/physics_layer_0/angular_velocity = 0.0 -2:15/0 = 0 -2:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:15/0/physics_layer_0/angular_velocity = 0.0 -3:15/0 = 0 -3:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:15/0/physics_layer_0/angular_velocity = 0.0 -4:15/0 = 0 -4:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:15/0/physics_layer_0/angular_velocity = 0.0 -5:15/0 = 0 -5:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:15/0/physics_layer_0/angular_velocity = 0.0 -6:15/0 = 0 -6:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:15/0/physics_layer_0/angular_velocity = 0.0 -7:15/0 = 0 -7:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:15/0/physics_layer_0/angular_velocity = 0.0 -8:15/0 = 0 -8:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:15/0/physics_layer_0/angular_velocity = 0.0 -9:15/0 = 0 -9:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:15/0/physics_layer_0/angular_velocity = 0.0 -10:15/0 = 0 -10:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:15/0/physics_layer_0/angular_velocity = 0.0 -11:15/0 = 0 -11:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:15/0/physics_layer_0/angular_velocity = 0.0 -12:15/0 = 0 -12:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:15/0/physics_layer_0/angular_velocity = 0.0 -13:15/0 = 0 -13:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:15/0/physics_layer_0/angular_velocity = 0.0 -14:15/0 = 0 -14:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:15/0/physics_layer_0/angular_velocity = 0.0 -15:15/0 = 0 -15:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:15/0/physics_layer_0/angular_velocity = 0.0 -16:15/0 = 0 -16:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:15/0/physics_layer_0/angular_velocity = 0.0 -17:15/0 = 0 -17:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:15/0/physics_layer_0/angular_velocity = 0.0 -18:15/0 = 0 -18:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:15/0/physics_layer_0/angular_velocity = 0.0 -19:15/0 = 0 -19:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:15/0/physics_layer_0/angular_velocity = 0.0 -20:15/0 = 0 -20:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:15/0/physics_layer_0/angular_velocity = 0.0 -21:15/0 = 0 -21:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:15/0/physics_layer_0/angular_velocity = 0.0 -22:15/0 = 0 -22:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:15/0/physics_layer_0/angular_velocity = 0.0 -23:15/0 = 0 -23:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:15/0/physics_layer_0/angular_velocity = 0.0 -24:15/0 = 0 -24:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:15/0/physics_layer_0/angular_velocity = 0.0 -25:15/0 = 0 -25:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:15/0/physics_layer_0/angular_velocity = 0.0 -26:15/0 = 0 -26:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:15/0/physics_layer_0/angular_velocity = 0.0 -27:15/0 = 0 -27:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:15/0/physics_layer_0/angular_velocity = 0.0 -28:15/0 = 0 -28:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:15/0/physics_layer_0/angular_velocity = 0.0 -29:15/0 = 0 -29:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:15/0/physics_layer_0/angular_velocity = 0.0 -30:15/0 = 0 -30:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:15/0/physics_layer_0/angular_velocity = 0.0 -31:15/0 = 0 -31:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:15/0/physics_layer_0/angular_velocity = 0.0 -32:15/0 = 0 -32:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:15/0/physics_layer_0/angular_velocity = 0.0 -33:15/0 = 0 -33:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:15/0/physics_layer_0/angular_velocity = 0.0 -34:15/0 = 0 -34:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:15/0/physics_layer_0/angular_velocity = 0.0 -35:15/0 = 0 -35:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:15/0/physics_layer_0/angular_velocity = 0.0 -36:15/0 = 0 -36:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:15/0/physics_layer_0/angular_velocity = 0.0 -37:15/0 = 0 -37:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:15/0/physics_layer_0/angular_velocity = 0.0 -38:15/0 = 0 -38:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:15/0/physics_layer_0/angular_velocity = 0.0 -39:15/0 = 0 -39:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:15/0/physics_layer_0/angular_velocity = 0.0 -40:15/0 = 0 -40:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:15/0/physics_layer_0/angular_velocity = 0.0 -41:15/0 = 0 -41:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:15/0/physics_layer_0/angular_velocity = 0.0 -42:15/0 = 0 -42:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:15/0/physics_layer_0/angular_velocity = 0.0 -43:15/0 = 0 -43:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:15/0/physics_layer_0/angular_velocity = 0.0 -44:15/0 = 0 -44:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:15/0/physics_layer_0/angular_velocity = 0.0 -45:15/0 = 0 -45:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:15/0/physics_layer_0/angular_velocity = 0.0 -46:15/0 = 0 -46:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:15/0/physics_layer_0/angular_velocity = 0.0 -47:15/0 = 0 -47:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:15/0/physics_layer_0/angular_velocity = 0.0 -48:15/0 = 0 -48:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:15/0/physics_layer_0/angular_velocity = 0.0 -0:16/0 = 0 -0:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:16/0/physics_layer_0/angular_velocity = 0.0 -1:16/0 = 0 -1:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:16/0/physics_layer_0/angular_velocity = 0.0 -2:16/0 = 0 -2:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:16/0/physics_layer_0/angular_velocity = 0.0 -3:16/0 = 0 -3:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:16/0/physics_layer_0/angular_velocity = 0.0 -4:16/0 = 0 -4:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:16/0/physics_layer_0/angular_velocity = 0.0 -5:16/0 = 0 -5:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:16/0/physics_layer_0/angular_velocity = 0.0 -6:16/0 = 0 -6:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:16/0/physics_layer_0/angular_velocity = 0.0 -7:16/0 = 0 -7:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:16/0/physics_layer_0/angular_velocity = 0.0 -8:16/0 = 0 -8:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:16/0/physics_layer_0/angular_velocity = 0.0 -9:16/0 = 0 -9:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:16/0/physics_layer_0/angular_velocity = 0.0 -10:16/0 = 0 -10:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:16/0/physics_layer_0/angular_velocity = 0.0 -11:16/0 = 0 -11:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:16/0/physics_layer_0/angular_velocity = 0.0 -12:16/0 = 0 -12:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:16/0/physics_layer_0/angular_velocity = 0.0 -13:16/0 = 0 -13:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:16/0/physics_layer_0/angular_velocity = 0.0 -14:16/0 = 0 -14:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:16/0/physics_layer_0/angular_velocity = 0.0 -15:16/0 = 0 -15:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:16/0/physics_layer_0/angular_velocity = 0.0 -16:16/0 = 0 -16:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:16/0/physics_layer_0/angular_velocity = 0.0 -17:16/0 = 0 -17:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:16/0/physics_layer_0/angular_velocity = 0.0 -18:16/0 = 0 -18:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:16/0/physics_layer_0/angular_velocity = 0.0 -19:16/0 = 0 -19:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:16/0/physics_layer_0/angular_velocity = 0.0 -20:16/0 = 0 -20:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:16/0/physics_layer_0/angular_velocity = 0.0 -21:16/0 = 0 -21:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:16/0/physics_layer_0/angular_velocity = 0.0 -22:16/0 = 0 -22:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:16/0/physics_layer_0/angular_velocity = 0.0 -23:16/0 = 0 -23:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:16/0/physics_layer_0/angular_velocity = 0.0 -24:16/0 = 0 -24:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:16/0/physics_layer_0/angular_velocity = 0.0 -25:16/0 = 0 -25:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:16/0/physics_layer_0/angular_velocity = 0.0 -26:16/0 = 0 -26:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:16/0/physics_layer_0/angular_velocity = 0.0 -27:16/0 = 0 -27:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:16/0/physics_layer_0/angular_velocity = 0.0 -28:16/0 = 0 -28:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:16/0/physics_layer_0/angular_velocity = 0.0 -29:16/0 = 0 -29:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:16/0/physics_layer_0/angular_velocity = 0.0 -30:16/0 = 0 -30:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:16/0/physics_layer_0/angular_velocity = 0.0 -31:16/0 = 0 -31:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:16/0/physics_layer_0/angular_velocity = 0.0 -32:16/0 = 0 -32:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:16/0/physics_layer_0/angular_velocity = 0.0 -33:16/0 = 0 -33:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:16/0/physics_layer_0/angular_velocity = 0.0 -34:16/0 = 0 -34:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:16/0/physics_layer_0/angular_velocity = 0.0 -35:16/0 = 0 -35:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:16/0/physics_layer_0/angular_velocity = 0.0 -36:16/0 = 0 -36:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:16/0/physics_layer_0/angular_velocity = 0.0 -37:16/0 = 0 -37:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:16/0/physics_layer_0/angular_velocity = 0.0 -38:16/0 = 0 -38:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:16/0/physics_layer_0/angular_velocity = 0.0 -39:16/0 = 0 -39:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:16/0/physics_layer_0/angular_velocity = 0.0 -40:16/0 = 0 -40:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:16/0/physics_layer_0/angular_velocity = 0.0 -41:16/0 = 0 -41:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:16/0/physics_layer_0/angular_velocity = 0.0 -42:16/0 = 0 -42:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:16/0/physics_layer_0/angular_velocity = 0.0 -43:16/0 = 0 -43:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:16/0/physics_layer_0/angular_velocity = 0.0 -44:16/0 = 0 -44:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:16/0/physics_layer_0/angular_velocity = 0.0 -45:16/0 = 0 -45:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:16/0/physics_layer_0/angular_velocity = 0.0 -46:16/0 = 0 -46:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:16/0/physics_layer_0/angular_velocity = 0.0 -47:16/0 = 0 -47:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:16/0/physics_layer_0/angular_velocity = 0.0 -48:16/0 = 0 -48:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:16/0/physics_layer_0/angular_velocity = 0.0 -0:17/0 = 0 -0:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:17/0/physics_layer_0/angular_velocity = 0.0 -1:17/0 = 0 -1:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:17/0/physics_layer_0/angular_velocity = 0.0 -2:17/0 = 0 -2:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:17/0/physics_layer_0/angular_velocity = 0.0 -3:17/0 = 0 -3:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:17/0/physics_layer_0/angular_velocity = 0.0 -4:17/0 = 0 -4:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:17/0/physics_layer_0/angular_velocity = 0.0 -5:17/0 = 0 -5:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:17/0/physics_layer_0/angular_velocity = 0.0 -6:17/0 = 0 -6:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:17/0/physics_layer_0/angular_velocity = 0.0 -7:17/0 = 0 -7:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:17/0/physics_layer_0/angular_velocity = 0.0 -8:17/0 = 0 -8:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:17/0/physics_layer_0/angular_velocity = 0.0 -9:17/0 = 0 -9:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:17/0/physics_layer_0/angular_velocity = 0.0 -10:17/0 = 0 -10:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:17/0/physics_layer_0/angular_velocity = 0.0 -11:17/0 = 0 -11:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:17/0/physics_layer_0/angular_velocity = 0.0 -12:17/0 = 0 -12:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:17/0/physics_layer_0/angular_velocity = 0.0 -13:17/0 = 0 -13:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:17/0/physics_layer_0/angular_velocity = 0.0 -14:17/0 = 0 -14:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:17/0/physics_layer_0/angular_velocity = 0.0 -15:17/0 = 0 -15:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:17/0/physics_layer_0/angular_velocity = 0.0 -16:17/0 = 0 -16:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:17/0/physics_layer_0/angular_velocity = 0.0 -17:17/0 = 0 -17:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:17/0/physics_layer_0/angular_velocity = 0.0 -18:17/0 = 0 -18:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:17/0/physics_layer_0/angular_velocity = 0.0 -19:17/0 = 0 -19:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:17/0/physics_layer_0/angular_velocity = 0.0 -20:17/0 = 0 -20:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:17/0/physics_layer_0/angular_velocity = 0.0 -21:17/0 = 0 -21:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:17/0/physics_layer_0/angular_velocity = 0.0 -22:17/0 = 0 -22:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:17/0/physics_layer_0/angular_velocity = 0.0 -23:17/0 = 0 -23:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:17/0/physics_layer_0/angular_velocity = 0.0 -24:17/0 = 0 -24:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:17/0/physics_layer_0/angular_velocity = 0.0 -25:17/0 = 0 -25:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:17/0/physics_layer_0/angular_velocity = 0.0 -26:17/0 = 0 -26:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:17/0/physics_layer_0/angular_velocity = 0.0 -27:17/0 = 0 -27:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:17/0/physics_layer_0/angular_velocity = 0.0 -28:17/0 = 0 -28:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:17/0/physics_layer_0/angular_velocity = 0.0 -29:17/0 = 0 -29:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:17/0/physics_layer_0/angular_velocity = 0.0 -30:17/0 = 0 -30:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:17/0/physics_layer_0/angular_velocity = 0.0 -31:17/0 = 0 -31:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:17/0/physics_layer_0/angular_velocity = 0.0 -32:17/0 = 0 -32:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:17/0/physics_layer_0/angular_velocity = 0.0 -33:17/0 = 0 -33:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:17/0/physics_layer_0/angular_velocity = 0.0 -34:17/0 = 0 -34:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:17/0/physics_layer_0/angular_velocity = 0.0 -35:17/0 = 0 -35:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:17/0/physics_layer_0/angular_velocity = 0.0 -36:17/0 = 0 -36:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:17/0/physics_layer_0/angular_velocity = 0.0 -37:17/0 = 0 -37:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:17/0/physics_layer_0/angular_velocity = 0.0 -38:17/0 = 0 -38:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:17/0/physics_layer_0/angular_velocity = 0.0 -39:17/0 = 0 -39:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:17/0/physics_layer_0/angular_velocity = 0.0 -40:17/0 = 0 -40:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:17/0/physics_layer_0/angular_velocity = 0.0 -41:17/0 = 0 -41:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:17/0/physics_layer_0/angular_velocity = 0.0 -42:17/0 = 0 -42:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:17/0/physics_layer_0/angular_velocity = 0.0 -43:17/0 = 0 -43:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:17/0/physics_layer_0/angular_velocity = 0.0 -44:17/0 = 0 -44:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:17/0/physics_layer_0/angular_velocity = 0.0 -45:17/0 = 0 -45:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:17/0/physics_layer_0/angular_velocity = 0.0 -46:17/0 = 0 -46:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:17/0/physics_layer_0/angular_velocity = 0.0 -47:17/0 = 0 -47:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:17/0/physics_layer_0/angular_velocity = 0.0 -48:17/0 = 0 -48:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:17/0/physics_layer_0/angular_velocity = 0.0 -0:18/0 = 0 -0:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:18/0/physics_layer_0/angular_velocity = 0.0 -1:18/0 = 0 -1:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:18/0/physics_layer_0/angular_velocity = 0.0 -2:18/0 = 0 -2:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:18/0/physics_layer_0/angular_velocity = 0.0 -3:18/0 = 0 -3:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:18/0/physics_layer_0/angular_velocity = 0.0 -4:18/0 = 0 -4:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:18/0/physics_layer_0/angular_velocity = 0.0 -5:18/0 = 0 -5:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:18/0/physics_layer_0/angular_velocity = 0.0 -6:18/0 = 0 -6:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:18/0/physics_layer_0/angular_velocity = 0.0 -7:18/0 = 0 -7:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:18/0/physics_layer_0/angular_velocity = 0.0 -8:18/0 = 0 -8:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:18/0/physics_layer_0/angular_velocity = 0.0 -9:18/0 = 0 -9:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:18/0/physics_layer_0/angular_velocity = 0.0 -10:18/0 = 0 -10:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:18/0/physics_layer_0/angular_velocity = 0.0 -11:18/0 = 0 -11:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:18/0/physics_layer_0/angular_velocity = 0.0 -12:18/0 = 0 -12:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:18/0/physics_layer_0/angular_velocity = 0.0 -13:18/0 = 0 -13:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:18/0/physics_layer_0/angular_velocity = 0.0 -14:18/0 = 0 -14:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:18/0/physics_layer_0/angular_velocity = 0.0 -15:18/0 = 0 -15:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:18/0/physics_layer_0/angular_velocity = 0.0 -16:18/0 = 0 -16:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:18/0/physics_layer_0/angular_velocity = 0.0 -17:18/0 = 0 -17:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:18/0/physics_layer_0/angular_velocity = 0.0 -18:18/0 = 0 -18:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:18/0/physics_layer_0/angular_velocity = 0.0 -19:18/0 = 0 -19:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:18/0/physics_layer_0/angular_velocity = 0.0 -20:18/0 = 0 -20:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:18/0/physics_layer_0/angular_velocity = 0.0 -21:18/0 = 0 -21:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:18/0/physics_layer_0/angular_velocity = 0.0 -22:18/0 = 0 -22:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:18/0/physics_layer_0/angular_velocity = 0.0 -23:18/0 = 0 -23:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:18/0/physics_layer_0/angular_velocity = 0.0 -24:18/0 = 0 -24:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:18/0/physics_layer_0/angular_velocity = 0.0 -25:18/0 = 0 -25:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:18/0/physics_layer_0/angular_velocity = 0.0 -26:18/0 = 0 -26:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:18/0/physics_layer_0/angular_velocity = 0.0 -27:18/0 = 0 -27:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:18/0/physics_layer_0/angular_velocity = 0.0 -28:18/0 = 0 -28:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:18/0/physics_layer_0/angular_velocity = 0.0 -29:18/0 = 0 -29:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:18/0/physics_layer_0/angular_velocity = 0.0 -30:18/0 = 0 -30:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:18/0/physics_layer_0/angular_velocity = 0.0 -31:18/0 = 0 -31:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:18/0/physics_layer_0/angular_velocity = 0.0 -32:18/0 = 0 -32:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:18/0/physics_layer_0/angular_velocity = 0.0 -33:18/0 = 0 -33:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:18/0/physics_layer_0/angular_velocity = 0.0 -34:18/0 = 0 -34:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:18/0/physics_layer_0/angular_velocity = 0.0 -35:18/0 = 0 -35:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:18/0/physics_layer_0/angular_velocity = 0.0 -36:18/0 = 0 -36:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:18/0/physics_layer_0/angular_velocity = 0.0 -37:18/0 = 0 -37:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:18/0/physics_layer_0/angular_velocity = 0.0 -38:18/0 = 0 -38:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:18/0/physics_layer_0/angular_velocity = 0.0 -39:18/0 = 0 -39:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:18/0/physics_layer_0/angular_velocity = 0.0 -40:18/0 = 0 -40:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:18/0/physics_layer_0/angular_velocity = 0.0 -41:18/0 = 0 -41:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:18/0/physics_layer_0/angular_velocity = 0.0 -42:18/0 = 0 -42:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:18/0/physics_layer_0/angular_velocity = 0.0 -43:18/0 = 0 -43:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:18/0/physics_layer_0/angular_velocity = 0.0 -44:18/0 = 0 -44:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:18/0/physics_layer_0/angular_velocity = 0.0 -45:18/0 = 0 -45:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:18/0/physics_layer_0/angular_velocity = 0.0 -46:18/0 = 0 -46:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:18/0/physics_layer_0/angular_velocity = 0.0 -47:18/0 = 0 -47:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:18/0/physics_layer_0/angular_velocity = 0.0 -48:18/0 = 0 -48:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:18/0/physics_layer_0/angular_velocity = 0.0 -0:19/0 = 0 -0:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:19/0/physics_layer_0/angular_velocity = 0.0 -1:19/0 = 0 -1:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:19/0/physics_layer_0/angular_velocity = 0.0 -2:19/0 = 0 -2:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:19/0/physics_layer_0/angular_velocity = 0.0 -3:19/0 = 0 -3:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:19/0/physics_layer_0/angular_velocity = 0.0 -4:19/0 = 0 -4:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:19/0/physics_layer_0/angular_velocity = 0.0 -5:19/0 = 0 -5:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:19/0/physics_layer_0/angular_velocity = 0.0 -6:19/0 = 0 -6:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:19/0/physics_layer_0/angular_velocity = 0.0 -7:19/0 = 0 -7:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:19/0/physics_layer_0/angular_velocity = 0.0 -8:19/0 = 0 -8:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:19/0/physics_layer_0/angular_velocity = 0.0 -9:19/0 = 0 -9:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:19/0/physics_layer_0/angular_velocity = 0.0 -10:19/0 = 0 -10:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:19/0/physics_layer_0/angular_velocity = 0.0 -11:19/0 = 0 -11:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:19/0/physics_layer_0/angular_velocity = 0.0 -12:19/0 = 0 -12:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:19/0/physics_layer_0/angular_velocity = 0.0 -13:19/0 = 0 -13:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:19/0/physics_layer_0/angular_velocity = 0.0 -14:19/0 = 0 -14:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:19/0/physics_layer_0/angular_velocity = 0.0 -15:19/0 = 0 -15:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:19/0/physics_layer_0/angular_velocity = 0.0 -16:19/0 = 0 -16:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:19/0/physics_layer_0/angular_velocity = 0.0 -17:19/0 = 0 -17:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:19/0/physics_layer_0/angular_velocity = 0.0 -18:19/0 = 0 -18:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:19/0/physics_layer_0/angular_velocity = 0.0 -19:19/0 = 0 -19:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:19/0/physics_layer_0/angular_velocity = 0.0 -20:19/0 = 0 -20:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:19/0/physics_layer_0/angular_velocity = 0.0 -21:19/0 = 0 -21:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:19/0/physics_layer_0/angular_velocity = 0.0 -22:19/0 = 0 -22:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:19/0/physics_layer_0/angular_velocity = 0.0 -23:19/0 = 0 -23:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:19/0/physics_layer_0/angular_velocity = 0.0 -24:19/0 = 0 -24:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:19/0/physics_layer_0/angular_velocity = 0.0 -25:19/0 = 0 -25:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:19/0/physics_layer_0/angular_velocity = 0.0 -26:19/0 = 0 -26:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:19/0/physics_layer_0/angular_velocity = 0.0 -27:19/0 = 0 -27:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:19/0/physics_layer_0/angular_velocity = 0.0 -28:19/0 = 0 -28:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:19/0/physics_layer_0/angular_velocity = 0.0 -29:19/0 = 0 -29:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:19/0/physics_layer_0/angular_velocity = 0.0 -30:19/0 = 0 -30:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:19/0/physics_layer_0/angular_velocity = 0.0 -31:19/0 = 0 -31:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:19/0/physics_layer_0/angular_velocity = 0.0 -32:19/0 = 0 -32:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:19/0/physics_layer_0/angular_velocity = 0.0 -33:19/0 = 0 -33:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:19/0/physics_layer_0/angular_velocity = 0.0 -34:19/0 = 0 -34:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:19/0/physics_layer_0/angular_velocity = 0.0 -35:19/0 = 0 -35:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:19/0/physics_layer_0/angular_velocity = 0.0 -36:19/0 = 0 -36:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:19/0/physics_layer_0/angular_velocity = 0.0 -37:19/0 = 0 -37:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:19/0/physics_layer_0/angular_velocity = 0.0 -38:19/0 = 0 -38:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:19/0/physics_layer_0/angular_velocity = 0.0 -39:19/0 = 0 -39:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:19/0/physics_layer_0/angular_velocity = 0.0 -40:19/0 = 0 -40:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:19/0/physics_layer_0/angular_velocity = 0.0 -41:19/0 = 0 -41:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:19/0/physics_layer_0/angular_velocity = 0.0 -42:19/0 = 0 -42:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:19/0/physics_layer_0/angular_velocity = 0.0 -43:19/0 = 0 -43:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:19/0/physics_layer_0/angular_velocity = 0.0 -44:19/0 = 0 -44:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:19/0/physics_layer_0/angular_velocity = 0.0 -45:19/0 = 0 -45:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:19/0/physics_layer_0/angular_velocity = 0.0 -46:19/0 = 0 -46:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:19/0/physics_layer_0/angular_velocity = 0.0 -47:19/0 = 0 -47:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:19/0/physics_layer_0/angular_velocity = 0.0 -48:19/0 = 0 -48:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:19/0/physics_layer_0/angular_velocity = 0.0 -0:20/0 = 0 -0:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:20/0/physics_layer_0/angular_velocity = 0.0 -1:20/0 = 0 -1:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:20/0/physics_layer_0/angular_velocity = 0.0 -2:20/0 = 0 -2:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:20/0/physics_layer_0/angular_velocity = 0.0 -3:20/0 = 0 -3:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:20/0/physics_layer_0/angular_velocity = 0.0 -4:20/0 = 0 -4:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:20/0/physics_layer_0/angular_velocity = 0.0 -5:20/0 = 0 -5:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:20/0/physics_layer_0/angular_velocity = 0.0 -6:20/0 = 0 -6:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:20/0/physics_layer_0/angular_velocity = 0.0 -7:20/0 = 0 -7:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:20/0/physics_layer_0/angular_velocity = 0.0 -8:20/0 = 0 -8:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:20/0/physics_layer_0/angular_velocity = 0.0 -9:20/0 = 0 -9:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:20/0/physics_layer_0/angular_velocity = 0.0 -10:20/0 = 0 -10:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:20/0/physics_layer_0/angular_velocity = 0.0 -11:20/0 = 0 -11:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:20/0/physics_layer_0/angular_velocity = 0.0 -12:20/0 = 0 -12:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:20/0/physics_layer_0/angular_velocity = 0.0 -13:20/0 = 0 -13:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:20/0/physics_layer_0/angular_velocity = 0.0 -14:20/0 = 0 -14:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:20/0/physics_layer_0/angular_velocity = 0.0 -15:20/0 = 0 -15:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:20/0/physics_layer_0/angular_velocity = 0.0 -16:20/0 = 0 -16:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:20/0/physics_layer_0/angular_velocity = 0.0 -17:20/0 = 0 -17:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:20/0/physics_layer_0/angular_velocity = 0.0 -18:20/0 = 0 -18:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:20/0/physics_layer_0/angular_velocity = 0.0 -19:20/0 = 0 -19:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:20/0/physics_layer_0/angular_velocity = 0.0 -20:20/0 = 0 -20:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:20/0/physics_layer_0/angular_velocity = 0.0 -21:20/0 = 0 -21:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:20/0/physics_layer_0/angular_velocity = 0.0 -22:20/0 = 0 -22:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:20/0/physics_layer_0/angular_velocity = 0.0 -23:20/0 = 0 -23:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:20/0/physics_layer_0/angular_velocity = 0.0 -24:20/0 = 0 -24:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:20/0/physics_layer_0/angular_velocity = 0.0 -25:20/0 = 0 -25:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:20/0/physics_layer_0/angular_velocity = 0.0 -26:20/0 = 0 -26:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:20/0/physics_layer_0/angular_velocity = 0.0 -27:20/0 = 0 -27:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:20/0/physics_layer_0/angular_velocity = 0.0 -28:20/0 = 0 -28:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:20/0/physics_layer_0/angular_velocity = 0.0 -29:20/0 = 0 -29:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:20/0/physics_layer_0/angular_velocity = 0.0 -30:20/0 = 0 -30:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:20/0/physics_layer_0/angular_velocity = 0.0 -31:20/0 = 0 -31:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:20/0/physics_layer_0/angular_velocity = 0.0 -32:20/0 = 0 -32:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:20/0/physics_layer_0/angular_velocity = 0.0 -33:20/0 = 0 -33:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:20/0/physics_layer_0/angular_velocity = 0.0 -34:20/0 = 0 -34:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:20/0/physics_layer_0/angular_velocity = 0.0 -35:20/0 = 0 -35:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:20/0/physics_layer_0/angular_velocity = 0.0 -36:20/0 = 0 -36:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:20/0/physics_layer_0/angular_velocity = 0.0 -37:20/0 = 0 -37:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:20/0/physics_layer_0/angular_velocity = 0.0 -38:20/0 = 0 -38:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:20/0/physics_layer_0/angular_velocity = 0.0 -39:20/0 = 0 -39:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:20/0/physics_layer_0/angular_velocity = 0.0 -40:20/0 = 0 -40:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:20/0/physics_layer_0/angular_velocity = 0.0 -41:20/0 = 0 -41:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:20/0/physics_layer_0/angular_velocity = 0.0 -42:20/0 = 0 -42:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:20/0/physics_layer_0/angular_velocity = 0.0 -43:20/0 = 0 -43:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:20/0/physics_layer_0/angular_velocity = 0.0 -44:20/0 = 0 -44:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:20/0/physics_layer_0/angular_velocity = 0.0 -45:20/0 = 0 -45:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:20/0/physics_layer_0/angular_velocity = 0.0 -46:20/0 = 0 -46:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:20/0/physics_layer_0/angular_velocity = 0.0 -47:20/0 = 0 -47:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:20/0/physics_layer_0/angular_velocity = 0.0 -48:20/0 = 0 -48:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:20/0/physics_layer_0/angular_velocity = 0.0 -0:21/0 = 0 -0:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -0:21/0/physics_layer_0/angular_velocity = 0.0 -1:21/0 = 0 -1:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -1:21/0/physics_layer_0/angular_velocity = 0.0 -2:21/0 = 0 -2:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -2:21/0/physics_layer_0/angular_velocity = 0.0 -3:21/0 = 0 -3:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -3:21/0/physics_layer_0/angular_velocity = 0.0 -4:21/0 = 0 -4:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -4:21/0/physics_layer_0/angular_velocity = 0.0 -5:21/0 = 0 -5:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -5:21/0/physics_layer_0/angular_velocity = 0.0 -6:21/0 = 0 -6:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -6:21/0/physics_layer_0/angular_velocity = 0.0 -7:21/0 = 0 -7:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -7:21/0/physics_layer_0/angular_velocity = 0.0 -8:21/0 = 0 -8:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -8:21/0/physics_layer_0/angular_velocity = 0.0 -9:21/0 = 0 -9:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -9:21/0/physics_layer_0/angular_velocity = 0.0 -10:21/0 = 0 -10:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -10:21/0/physics_layer_0/angular_velocity = 0.0 -11:21/0 = 0 -11:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -11:21/0/physics_layer_0/angular_velocity = 0.0 -12:21/0 = 0 -12:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -12:21/0/physics_layer_0/angular_velocity = 0.0 -13:21/0 = 0 -13:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -13:21/0/physics_layer_0/angular_velocity = 0.0 -14:21/0 = 0 -14:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -14:21/0/physics_layer_0/angular_velocity = 0.0 -15:21/0 = 0 -15:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -15:21/0/physics_layer_0/angular_velocity = 0.0 -16:21/0 = 0 -16:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -16:21/0/physics_layer_0/angular_velocity = 0.0 -17:21/0 = 0 -17:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -17:21/0/physics_layer_0/angular_velocity = 0.0 -18:21/0 = 0 -18:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:21/0/physics_layer_0/angular_velocity = 0.0 -19:21/0 = 0 -19:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -19:21/0/physics_layer_0/angular_velocity = 0.0 -20:21/0 = 0 -20:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -20:21/0/physics_layer_0/angular_velocity = 0.0 -21:21/0 = 0 -21:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -21:21/0/physics_layer_0/angular_velocity = 0.0 -22:21/0 = 0 -22:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -22:21/0/physics_layer_0/angular_velocity = 0.0 -23:21/0 = 0 -23:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -23:21/0/physics_layer_0/angular_velocity = 0.0 -24:21/0 = 0 -24:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -24:21/0/physics_layer_0/angular_velocity = 0.0 -25:21/0 = 0 -25:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -25:21/0/physics_layer_0/angular_velocity = 0.0 -26:21/0 = 0 -26:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -26:21/0/physics_layer_0/angular_velocity = 0.0 -27:21/0 = 0 -27:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -27:21/0/physics_layer_0/angular_velocity = 0.0 -28:21/0 = 0 -28:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -28:21/0/physics_layer_0/angular_velocity = 0.0 -29:21/0 = 0 -29:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -29:21/0/physics_layer_0/angular_velocity = 0.0 -30:21/0 = 0 -30:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -30:21/0/physics_layer_0/angular_velocity = 0.0 -31:21/0 = 0 -31:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -31:21/0/physics_layer_0/angular_velocity = 0.0 -32:21/0 = 0 -32:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -32:21/0/physics_layer_0/angular_velocity = 0.0 -33:21/0 = 0 -33:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -33:21/0/physics_layer_0/angular_velocity = 0.0 -34:21/0 = 0 -34:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -34:21/0/physics_layer_0/angular_velocity = 0.0 -35:21/0 = 0 -35:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -35:21/0/physics_layer_0/angular_velocity = 0.0 -36:21/0 = 0 -36:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -36:21/0/physics_layer_0/angular_velocity = 0.0 -37:21/0 = 0 -37:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -37:21/0/physics_layer_0/angular_velocity = 0.0 -38:21/0 = 0 -38:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -38:21/0/physics_layer_0/angular_velocity = 0.0 -39:21/0 = 0 -39:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -39:21/0/physics_layer_0/angular_velocity = 0.0 -40:21/0 = 0 -40:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -40:21/0/physics_layer_0/angular_velocity = 0.0 -41:21/0 = 0 -41:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -41:21/0/physics_layer_0/angular_velocity = 0.0 -42:21/0 = 0 -42:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -42:21/0/physics_layer_0/angular_velocity = 0.0 -43:21/0 = 0 -43:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -43:21/0/physics_layer_0/angular_velocity = 0.0 -44:21/0 = 0 -44:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -44:21/0/physics_layer_0/angular_velocity = 0.0 -45:21/0 = 0 -45:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -45:21/0/physics_layer_0/angular_velocity = 0.0 -46:21/0 = 0 -46:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -46:21/0/physics_layer_0/angular_velocity = 0.0 -47:21/0 = 0 -47:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -47:21/0/physics_layer_0/angular_velocity = 0.0 -48:21/0 = 0 -48:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) -48:21/0/physics_layer_0/angular_velocity = 0.0 -18:0/0 = 0 -18:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) -18:0/0/physics_layer_0/angular_velocity = 0.0 -18:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) - -[sub_resource type="TileSetScenesCollectionSource" id="TileSetScenesCollectionSource_mi6dp"] -scenes/1/scene = ExtResource("2_win2x") - -[sub_resource type="TileSet" id="TileSet_0u0tf"] -physics_layer_0/collision_layer = 1 -sources/1 = SubResource("TileSetAtlasSource_ari5a") -sources/3 = SubResource("TileSetScenesCollectionSource_mi6dp") +[ext_resource type="Texture2D" uid="uid://5kstmna3yb6t" path="res://assets/white.png" id="6_8laen"] +[ext_resource type="FontFile" uid="uid://ddjw625xpmwtc" path="res://assets/Not Jam UI Condensed 16.ttf" id="6_sa7lc"] [node name="Main" type="Node2D"] script = ExtResource("1_8hq0w") @@ -3262,16 +14,10 @@ script = ExtResource("1_8hq0w") [node name="Player" parent="." instance=ExtResource("2_ekt33")] position = Vector2(80, 48) -[node name="Map" type="Node2D" parent="."] - -[node name="TileMap" type="TileMap" parent="Map"] -tile_set = SubResource("TileSet_0u0tf") -format = 2 -layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 196617, 0, 131072) -layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 262152, 3, 65536, 327689, 3, 65536, 327690, 3, 65536, 327691, 3, 65536, 262156, 3, 65536, 196620, 3, 65536, 131084, 3, 65536, 131083, 3, 65536, 131082, 3, 65536, 131081, 3, 65536, 196617, 3, 65536, 196616, 3, 65536, 327688, 3, 65536, 393224, 3, 65536, 393225, 3, 65536, 458761, 3, 65536, 458762, 3, 65536, 458763, 3, 65536, 458764, 3, 65536, 393228, 3, 65536, 393229, 3, 65536, 327693, 3, 65536, 262157, 3, 65536, 196621, 3, 65536, 131085, 3, 65536, 65548, 3, 65536, 65547, 3, 65536, 65546, 3, 65536, 65545, 3, 65536, 65544, 3, 65536, 65549, 3, 65536, 131086, 3, 65536, 196622, 3, 65536, 196623, 3, 65536) +[node name="Map" parent="." instance=ExtResource("3_w444g")] [node name="UI" type="Control" parent="."] +top_level = true layout_mode = 3 anchors_preset = 0 offset_right = 256.0 @@ -3290,6 +36,57 @@ offset_bottom = 128.0 layout_mode = 0 offset_right = 224.0 offset_bottom = 32.0 -theme_override_font_sizes/font_size = 10 +theme_override_fonts/font = ExtResource("6_sa7lc") +theme_override_font_sizes/font_size = 16 text = "I told you to not let Jayden make the ui bruh!!!" autowrap_mode = 2 + +[node name="HUD" type="Control" parent="UI"] +anchors_preset = 0 +offset_right = 256.0 +offset_bottom = 16.0 + +[node name="Bar" type="TextureRect" parent="UI/HUD"] +layout_mode = 2 +offset_right = 256.0 +offset_bottom = 17.0 +texture = ExtResource("6_8laen") + +[node name="BootIcon" type="Sprite2D" parent="UI/HUD"] +visible = false +modulate = Color(0, 0, 0, 1) +position = Vector2(160, 0) +texture = ExtResource("1_kghfi") +centered = false +region_enabled = true +region_rect = Rect2(640, 16, 16, 16) + +[node name="HPLabel" type="Label" parent="UI/HUD"] +layout_mode = 2 +offset_left = 16.0 +offset_right = 54.0 +offset_bottom = 16.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_fonts/font = ExtResource("6_sa7lc") +theme_override_font_sizes/font_size = 16 +text = "HP: 3/3" + +[node name="HPLabel2" type="Label" parent="UI/HUD"] +layout_mode = 2 +offset_left = 192.0 +offset_right = 206.0 +offset_bottom = 16.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_fonts/font = ExtResource("6_sa7lc") +theme_override_font_sizes/font_size = 16 +text = "0g" + +[node name="HPLabel3" type="Label" parent="UI/HUD"] +layout_mode = 2 +offset_left = 224.0 +offset_right = 262.0 +offset_bottom = 16.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_fonts/font = ExtResource("6_sa7lc") +theme_override_font_sizes/font_size = 16 +text = "B00" diff --git a/src/main/ui.gd b/src/main/ui.gd index 9d0ea58..bdde533 100644 --- a/src/main/ui.gd +++ b/src/main/ui.gd @@ -2,6 +2,7 @@ class_name UI extends Control @onready var textbox:Panel = $Textbox +@onready var bootIcon:Sprite2D =$HUD/BootIcon signal text_rendered signal text_removed signal text_advanced @@ -10,6 +11,7 @@ signal text_advanced func render_text(new_text_arr) -> void: #loop through the array and display the lines of text text_rendered.emit() + bootIcon.visible = true textbox.visible = true var textLabel = $Textbox/Text #i = 0 diff --git a/src/maps/map-1.tscn b/src/maps/map-1.tscn new file mode 100644 index 0000000..5699bf0 --- /dev/null +++ b/src/maps/map-1.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=3 format=3 uid="uid://deqm4to4ptnq0"] + +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_vosps"] +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_web8r"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_web8r") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("1_vosps") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 196615, 3, 262144, 393226, 3, 196608) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 48) diff --git a/src/maps/map-2.tscn b/src/maps/map-2.tscn new file mode 100644 index 0000000..edb017b --- /dev/null +++ b/src/maps/map-2.tscn @@ -0,0 +1,15 @@ +[gd_scene load_steps=2 format=3 uid="uid://cwxdotd7hh5tb"] + +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_2mk3g"] + +[node name="Map" type="Node2D"] + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("1_2mk3g") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 393219, 3, 196608, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 64) diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn new file mode 100644 index 0000000..192567e --- /dev/null +++ b/src/maps/map-3.tscn @@ -0,0 +1,15 @@ +[gd_scene load_steps=2 format=3 uid="uid://bapnj7ekqfb0t"] + +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_xfyi1"] + +[node name="Map" type="Node2D"] + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("1_xfyi1") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458762, 262145, 18, 458761, 262145, 18, 65550, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 262157, 262145, 18, 196621, 262145, 18, 196620, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 327688, 262145, 18, 393224, 262145, 18, 393223, 262145, 18, 327687, 262145, 18, 327686, 262145, 18, 262150, 262145, 18, 196614, 262145, 18, 196613, 262145, 18, 196612, 262145, 18, 262148, 262145, 18, 262147, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 327685, 262145, 18, 393225, 262145, 18, 393226, 262145, 18, 393227, 262145, 18, 393228, 262145, 18, 393229, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 327693, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 196615, 262145, 18, 262151, 262145, 18, 131082, 3, 262144, 327692, 3, 196608) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(144, 48) diff --git a/src/maps/map.gd b/src/maps/map.gd new file mode 100644 index 0000000..fe88449 --- /dev/null +++ b/src/maps/map.gd @@ -0,0 +1,12 @@ +class_name Map +extends Node2D + + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + pass diff --git a/src/player/player.gd b/src/player/player.gd index db267f8..a6bfd75 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -3,6 +3,8 @@ extends Area2D @onready var raycast := $RayCast2D +signal walked_into_stairs + const TILE_SIZE := 16 var is_actionable:= true @@ -12,6 +14,7 @@ func _init() -> void: func _ready() -> void: raycast.collide_with_areas = true + func get_input_vector(event: InputEvent) -> Vector2: # make vector representing player input var dir := Vector2.ZERO @@ -39,7 +42,6 @@ func _input(event: InputEvent) -> void: _inspect() - func _move(_input_dir:Vector2) -> void: raycast.target_position = _input_dir * TILE_SIZE # clear old raycast collison then get new one @@ -48,8 +50,11 @@ func _move(_input_dir:Vector2) -> void: if next_tile != null: print(next_tile) - else: + + if next_tile == null: position += _input_dir * TILE_SIZE + elif next_tile.is_in_group('stairs'): + walked_into_stairs.emit() func _inspect() -> void: diff --git a/src/player/player.tscn b/src/player/player.tscn index e362576..6c7d3be 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -9,16 +9,16 @@ size = Vector2(16, 16) [node name="Player" type="Area2D"] script = ExtResource("1_fqi5k") +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(8, 8) +shape = SubResource("RectangleShape2D_v5s8d") + [node name="Sprite2D" type="Sprite2D" parent="."] texture = ExtResource("1_bwexj") centered = false region_enabled = true region_rect = Rect2(432, 0, 16, 16) -[node name="CollisionShape2D" type="CollisionShape2D" parent="."] -position = Vector2(8, 8) -shape = SubResource("RectangleShape2D_v5s8d") - [node name="RayCast2D" type="RayCast2D" parent="."] position = Vector2(8, 8) target_position = Vector2(0, 16) diff --git a/src/resources/map_tileset.tres b/src/resources/map_tileset.tres new file mode 100644 index 0000000..e471ef7 --- /dev/null +++ b/src/resources/map_tileset.tres @@ -0,0 +1,3256 @@ +[gd_resource type="TileSet" load_steps=6 format=3 uid="uid://dmwbt07hsdtyl"] + +[ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_q6o4g"] +[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="2_poklm"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_uqirg"] + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ari5a"] +texture = ExtResource("1_q6o4g") +1:0/0 = 0 +1:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:0/0/physics_layer_0/angular_velocity = 0.0 +2:0/0 = 0 +2:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:0/0/physics_layer_0/angular_velocity = 0.0 +3:0/0 = 0 +3:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:0/0/physics_layer_0/angular_velocity = 0.0 +4:0/0 = 0 +4:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:0/0/physics_layer_0/angular_velocity = 0.0 +5:0/0 = 0 +5:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:0/0/physics_layer_0/angular_velocity = 0.0 +6:0/0 = 0 +6:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:0/0/physics_layer_0/angular_velocity = 0.0 +7:0/0 = 0 +7:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:0/0/physics_layer_0/angular_velocity = 0.0 +8:0/0 = 0 +8:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:0/0/physics_layer_0/angular_velocity = 0.0 +9:0/0 = 0 +9:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:0/0/physics_layer_0/angular_velocity = 0.0 +10:0/0 = 0 +10:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:0/0/physics_layer_0/angular_velocity = 0.0 +11:0/0 = 0 +11:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:0/0/physics_layer_0/angular_velocity = 0.0 +12:0/0 = 0 +12:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:0/0/physics_layer_0/angular_velocity = 0.0 +13:0/0 = 0 +13:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:0/0/physics_layer_0/angular_velocity = 0.0 +14:0/0 = 0 +14:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:0/0/physics_layer_0/angular_velocity = 0.0 +15:0/0 = 0 +15:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:0/0/physics_layer_0/angular_velocity = 0.0 +16:0/0 = 0 +16:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:0/0/physics_layer_0/angular_velocity = 0.0 +17:0/0 = 0 +17:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:0/0/physics_layer_0/angular_velocity = 0.0 +19:0/0 = 0 +19:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:0/0/physics_layer_0/angular_velocity = 0.0 +19:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +20:0/0 = 0 +20:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:0/0/physics_layer_0/angular_velocity = 0.0 +20:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +21:0/0 = 0 +21:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:0/0/physics_layer_0/angular_velocity = 0.0 +22:0/0 = 0 +22:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:0/0/physics_layer_0/angular_velocity = 0.0 +23:0/0 = 0 +23:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:0/0/physics_layer_0/angular_velocity = 0.0 +24:0/0 = 0 +24:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:0/0/physics_layer_0/angular_velocity = 0.0 +25:0/0 = 0 +25:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:0/0/physics_layer_0/angular_velocity = 0.0 +26:0/0 = 0 +26:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:0/0/physics_layer_0/angular_velocity = 0.0 +27:0/0 = 0 +27:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:0/0/physics_layer_0/angular_velocity = 0.0 +28:0/0 = 0 +28:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:0/0/physics_layer_0/angular_velocity = 0.0 +29:0/0 = 0 +29:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:0/0/physics_layer_0/angular_velocity = 0.0 +30:0/0 = 0 +30:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:0/0/physics_layer_0/angular_velocity = 0.0 +31:0/0 = 0 +31:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:0/0/physics_layer_0/angular_velocity = 0.0 +32:0/0 = 0 +32:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:0/0/physics_layer_0/angular_velocity = 0.0 +33:0/0 = 0 +33:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:0/0/physics_layer_0/angular_velocity = 0.0 +34:0/0 = 0 +34:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:0/0/physics_layer_0/angular_velocity = 0.0 +35:0/0 = 0 +35:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:0/0/physics_layer_0/angular_velocity = 0.0 +36:0/0 = 0 +36:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:0/0/physics_layer_0/angular_velocity = 0.0 +37:0/0 = 0 +37:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:0/0/physics_layer_0/angular_velocity = 0.0 +38:0/0 = 0 +38:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:0/0/physics_layer_0/angular_velocity = 0.0 +39:0/0 = 0 +39:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:0/0/physics_layer_0/angular_velocity = 0.0 +40:0/0 = 0 +40:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:0/0/physics_layer_0/angular_velocity = 0.0 +41:0/0 = 0 +41:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:0/0/physics_layer_0/angular_velocity = 0.0 +42:0/0 = 0 +42:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:0/0/physics_layer_0/angular_velocity = 0.0 +43:0/0 = 0 +43:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:0/0/physics_layer_0/angular_velocity = 0.0 +44:0/0 = 0 +44:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:0/0/physics_layer_0/angular_velocity = 0.0 +45:0/0 = 0 +45:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:0/0/physics_layer_0/angular_velocity = 0.0 +46:0/0 = 0 +46:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:0/0/physics_layer_0/angular_velocity = 0.0 +47:0/0 = 0 +47:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:0/0/physics_layer_0/angular_velocity = 0.0 +48:0/0 = 0 +48:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:0/0/physics_layer_0/angular_velocity = 0.0 +0:1/0 = 0 +0:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:1/0/physics_layer_0/angular_velocity = 0.0 +1:1/0 = 0 +1:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:1/0/physics_layer_0/angular_velocity = 0.0 +2:1/0 = 0 +2:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:1/0/physics_layer_0/angular_velocity = 0.0 +3:1/0 = 0 +3:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:1/0/physics_layer_0/angular_velocity = 0.0 +4:1/0 = 0 +4:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:1/0/physics_layer_0/angular_velocity = 0.0 +5:1/0 = 0 +5:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:1/0/physics_layer_0/angular_velocity = 0.0 +6:1/0 = 0 +6:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:1/0/physics_layer_0/angular_velocity = 0.0 +7:1/0 = 0 +7:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:1/0/physics_layer_0/angular_velocity = 0.0 +8:1/0 = 0 +8:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:1/0/physics_layer_0/angular_velocity = 0.0 +9:1/0 = 0 +9:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:1/0/physics_layer_0/angular_velocity = 0.0 +10:1/0 = 0 +10:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:1/0/physics_layer_0/angular_velocity = 0.0 +11:1/0 = 0 +11:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:1/0/physics_layer_0/angular_velocity = 0.0 +12:1/0 = 0 +12:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:1/0/physics_layer_0/angular_velocity = 0.0 +13:1/0 = 0 +13:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:1/0/physics_layer_0/angular_velocity = 0.0 +14:1/0 = 0 +14:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:1/0/physics_layer_0/angular_velocity = 0.0 +15:1/0 = 0 +15:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:1/0/physics_layer_0/angular_velocity = 0.0 +16:1/0 = 0 +16:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:1/0/physics_layer_0/angular_velocity = 0.0 +17:1/0 = 0 +17:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:1/0/physics_layer_0/angular_velocity = 0.0 +18:1/0 = 0 +18:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:1/0/physics_layer_0/angular_velocity = 0.0 +18:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +19:1/0 = 0 +19:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:1/0/physics_layer_0/angular_velocity = 0.0 +20:1/0 = 0 +20:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:1/0/physics_layer_0/angular_velocity = 0.0 +20:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +21:1/0 = 0 +21:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:1/0/physics_layer_0/angular_velocity = 0.0 +22:1/0 = 0 +22:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:1/0/physics_layer_0/angular_velocity = 0.0 +23:1/0 = 0 +23:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:1/0/physics_layer_0/angular_velocity = 0.0 +24:1/0 = 0 +24:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:1/0/physics_layer_0/angular_velocity = 0.0 +25:1/0 = 0 +25:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:1/0/physics_layer_0/angular_velocity = 0.0 +26:1/0 = 0 +26:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:1/0/physics_layer_0/angular_velocity = 0.0 +27:1/0 = 0 +27:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:1/0/physics_layer_0/angular_velocity = 0.0 +28:1/0 = 0 +28:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:1/0/physics_layer_0/angular_velocity = 0.0 +29:1/0 = 0 +29:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:1/0/physics_layer_0/angular_velocity = 0.0 +30:1/0 = 0 +30:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:1/0/physics_layer_0/angular_velocity = 0.0 +31:1/0 = 0 +31:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:1/0/physics_layer_0/angular_velocity = 0.0 +32:1/0 = 0 +32:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:1/0/physics_layer_0/angular_velocity = 0.0 +33:1/0 = 0 +33:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:1/0/physics_layer_0/angular_velocity = 0.0 +34:1/0 = 0 +34:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:1/0/physics_layer_0/angular_velocity = 0.0 +35:1/0 = 0 +35:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:1/0/physics_layer_0/angular_velocity = 0.0 +36:1/0 = 0 +36:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:1/0/physics_layer_0/angular_velocity = 0.0 +37:1/0 = 0 +37:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:1/0/physics_layer_0/angular_velocity = 0.0 +38:1/0 = 0 +38:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:1/0/physics_layer_0/angular_velocity = 0.0 +39:1/0 = 0 +39:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:1/0/physics_layer_0/angular_velocity = 0.0 +40:1/0 = 0 +40:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:1/0/physics_layer_0/angular_velocity = 0.0 +41:1/0 = 0 +41:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:1/0/physics_layer_0/angular_velocity = 0.0 +42:1/0 = 0 +42:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:1/0/physics_layer_0/angular_velocity = 0.0 +43:1/0 = 0 +43:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:1/0/physics_layer_0/angular_velocity = 0.0 +44:1/0 = 0 +44:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:1/0/physics_layer_0/angular_velocity = 0.0 +45:1/0 = 0 +45:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:1/0/physics_layer_0/angular_velocity = 0.0 +46:1/0 = 0 +46:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:1/0/physics_layer_0/angular_velocity = 0.0 +47:1/0 = 0 +47:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:1/0/physics_layer_0/angular_velocity = 0.0 +48:1/0 = 0 +48:1/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:1/0/physics_layer_0/angular_velocity = 0.0 +0:2/0 = 0 +0:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:2/0/physics_layer_0/angular_velocity = 0.0 +1:2/0 = 0 +1:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:2/0/physics_layer_0/angular_velocity = 0.0 +2:2/0 = 0 +2:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:2/0/physics_layer_0/angular_velocity = 0.0 +3:2/0 = 0 +3:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:2/0/physics_layer_0/angular_velocity = 0.0 +4:2/0 = 0 +4:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:2/0/physics_layer_0/angular_velocity = 0.0 +5:2/0 = 0 +5:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:2/0/physics_layer_0/angular_velocity = 0.0 +6:2/0 = 0 +6:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:2/0/physics_layer_0/angular_velocity = 0.0 +7:2/0 = 0 +7:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:2/0/physics_layer_0/angular_velocity = 0.0 +8:2/0 = 0 +8:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:2/0/physics_layer_0/angular_velocity = 0.0 +9:2/0 = 0 +9:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:2/0/physics_layer_0/angular_velocity = 0.0 +10:2/0 = 0 +10:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:2/0/physics_layer_0/angular_velocity = 0.0 +11:2/0 = 0 +11:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:2/0/physics_layer_0/angular_velocity = 0.0 +12:2/0 = 0 +12:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:2/0/physics_layer_0/angular_velocity = 0.0 +13:2/0 = 0 +13:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:2/0/physics_layer_0/angular_velocity = 0.0 +14:2/0 = 0 +14:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:2/0/physics_layer_0/angular_velocity = 0.0 +15:2/0 = 0 +15:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:2/0/physics_layer_0/angular_velocity = 0.0 +16:2/0 = 0 +16:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:2/0/physics_layer_0/angular_velocity = 0.0 +17:2/0 = 0 +17:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:2/0/physics_layer_0/angular_velocity = 0.0 +18:2/0 = 0 +18:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:2/0/physics_layer_0/angular_velocity = 0.0 +18:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +19:2/0 = 0 +19:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:2/0/physics_layer_0/angular_velocity = 0.0 +19:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +20:2/0 = 0 +20:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:2/0/physics_layer_0/angular_velocity = 0.0 +20:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) +21:2/0 = 0 +21:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:2/0/physics_layer_0/angular_velocity = 0.0 +22:2/0 = 0 +22:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:2/0/physics_layer_0/angular_velocity = 0.0 +23:2/0 = 0 +23:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:2/0/physics_layer_0/angular_velocity = 0.0 +24:2/0 = 0 +24:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:2/0/physics_layer_0/angular_velocity = 0.0 +25:2/0 = 0 +25:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:2/0/physics_layer_0/angular_velocity = 0.0 +26:2/0 = 0 +26:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:2/0/physics_layer_0/angular_velocity = 0.0 +27:2/0 = 0 +27:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:2/0/physics_layer_0/angular_velocity = 0.0 +28:2/0 = 0 +28:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:2/0/physics_layer_0/angular_velocity = 0.0 +29:2/0 = 0 +29:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:2/0/physics_layer_0/angular_velocity = 0.0 +30:2/0 = 0 +30:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:2/0/physics_layer_0/angular_velocity = 0.0 +31:2/0 = 0 +31:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:2/0/physics_layer_0/angular_velocity = 0.0 +32:2/0 = 0 +32:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:2/0/physics_layer_0/angular_velocity = 0.0 +33:2/0 = 0 +33:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:2/0/physics_layer_0/angular_velocity = 0.0 +34:2/0 = 0 +34:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:2/0/physics_layer_0/angular_velocity = 0.0 +35:2/0 = 0 +35:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:2/0/physics_layer_0/angular_velocity = 0.0 +36:2/0 = 0 +36:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:2/0/physics_layer_0/angular_velocity = 0.0 +37:2/0 = 0 +37:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:2/0/physics_layer_0/angular_velocity = 0.0 +38:2/0 = 0 +38:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:2/0/physics_layer_0/angular_velocity = 0.0 +39:2/0 = 0 +39:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:2/0/physics_layer_0/angular_velocity = 0.0 +40:2/0 = 0 +40:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:2/0/physics_layer_0/angular_velocity = 0.0 +41:2/0 = 0 +41:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:2/0/physics_layer_0/angular_velocity = 0.0 +42:2/0 = 0 +42:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:2/0/physics_layer_0/angular_velocity = 0.0 +43:2/0 = 0 +43:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:2/0/physics_layer_0/angular_velocity = 0.0 +44:2/0 = 0 +44:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:2/0/physics_layer_0/angular_velocity = 0.0 +45:2/0 = 0 +45:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:2/0/physics_layer_0/angular_velocity = 0.0 +46:2/0 = 0 +46:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:2/0/physics_layer_0/angular_velocity = 0.0 +47:2/0 = 0 +47:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:2/0/physics_layer_0/angular_velocity = 0.0 +48:2/0 = 0 +48:2/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:2/0/physics_layer_0/angular_velocity = 0.0 +0:3/0 = 0 +0:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:3/0/physics_layer_0/angular_velocity = 0.0 +1:3/0 = 0 +1:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:3/0/physics_layer_0/angular_velocity = 0.0 +2:3/0 = 0 +2:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:3/0/physics_layer_0/angular_velocity = 0.0 +3:3/0 = 0 +3:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:3/0/physics_layer_0/angular_velocity = 0.0 +4:3/0 = 0 +4:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:3/0/physics_layer_0/angular_velocity = 0.0 +5:3/0 = 0 +5:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:3/0/physics_layer_0/angular_velocity = 0.0 +6:3/0 = 0 +6:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:3/0/physics_layer_0/angular_velocity = 0.0 +7:3/0 = 0 +7:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:3/0/physics_layer_0/angular_velocity = 0.0 +8:3/0 = 0 +8:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:3/0/physics_layer_0/angular_velocity = 0.0 +9:3/0 = 0 +9:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:3/0/physics_layer_0/angular_velocity = 0.0 +10:3/0 = 0 +10:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:3/0/physics_layer_0/angular_velocity = 0.0 +11:3/0 = 0 +11:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:3/0/physics_layer_0/angular_velocity = 0.0 +12:3/0 = 0 +12:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:3/0/physics_layer_0/angular_velocity = 0.0 +13:3/0 = 0 +13:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:3/0/physics_layer_0/angular_velocity = 0.0 +14:3/0 = 0 +14:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:3/0/physics_layer_0/angular_velocity = 0.0 +15:3/0 = 0 +15:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:3/0/physics_layer_0/angular_velocity = 0.0 +16:3/0 = 0 +16:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:3/0/physics_layer_0/angular_velocity = 0.0 +17:3/0 = 0 +17:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:3/0/physics_layer_0/angular_velocity = 0.0 +18:3/0 = 0 +18:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:3/0/physics_layer_0/angular_velocity = 0.0 +19:3/0 = 0 +19:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:3/0/physics_layer_0/angular_velocity = 0.0 +20:3/0 = 0 +20:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:3/0/physics_layer_0/angular_velocity = 0.0 +21:3/0 = 0 +21:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:3/0/physics_layer_0/angular_velocity = 0.0 +22:3/0 = 0 +22:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:3/0/physics_layer_0/angular_velocity = 0.0 +23:3/0 = 0 +23:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:3/0/physics_layer_0/angular_velocity = 0.0 +24:3/0 = 0 +24:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:3/0/physics_layer_0/angular_velocity = 0.0 +25:3/0 = 0 +25:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:3/0/physics_layer_0/angular_velocity = 0.0 +26:3/0 = 0 +26:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:3/0/physics_layer_0/angular_velocity = 0.0 +27:3/0 = 0 +27:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:3/0/physics_layer_0/angular_velocity = 0.0 +28:3/0 = 0 +28:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:3/0/physics_layer_0/angular_velocity = 0.0 +29:3/0 = 0 +29:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:3/0/physics_layer_0/angular_velocity = 0.0 +30:3/0 = 0 +30:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:3/0/physics_layer_0/angular_velocity = 0.0 +31:3/0 = 0 +31:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:3/0/physics_layer_0/angular_velocity = 0.0 +32:3/0 = 0 +32:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:3/0/physics_layer_0/angular_velocity = 0.0 +33:3/0 = 0 +33:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:3/0/physics_layer_0/angular_velocity = 0.0 +34:3/0 = 0 +34:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:3/0/physics_layer_0/angular_velocity = 0.0 +35:3/0 = 0 +35:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:3/0/physics_layer_0/angular_velocity = 0.0 +36:3/0 = 0 +36:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:3/0/physics_layer_0/angular_velocity = 0.0 +37:3/0 = 0 +37:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:3/0/physics_layer_0/angular_velocity = 0.0 +38:3/0 = 0 +38:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:3/0/physics_layer_0/angular_velocity = 0.0 +39:3/0 = 0 +39:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:3/0/physics_layer_0/angular_velocity = 0.0 +40:3/0 = 0 +40:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:3/0/physics_layer_0/angular_velocity = 0.0 +41:3/0 = 0 +41:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:3/0/physics_layer_0/angular_velocity = 0.0 +42:3/0 = 0 +42:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:3/0/physics_layer_0/angular_velocity = 0.0 +43:3/0 = 0 +43:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:3/0/physics_layer_0/angular_velocity = 0.0 +44:3/0 = 0 +44:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:3/0/physics_layer_0/angular_velocity = 0.0 +45:3/0 = 0 +45:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:3/0/physics_layer_0/angular_velocity = 0.0 +46:3/0 = 0 +46:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:3/0/physics_layer_0/angular_velocity = 0.0 +47:3/0 = 0 +47:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:3/0/physics_layer_0/angular_velocity = 0.0 +48:3/0 = 0 +48:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:3/0/physics_layer_0/angular_velocity = 0.0 +0:4/0 = 0 +0:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:4/0/physics_layer_0/angular_velocity = 0.0 +1:4/0 = 0 +1:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:4/0/physics_layer_0/angular_velocity = 0.0 +2:4/0 = 0 +2:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:4/0/physics_layer_0/angular_velocity = 0.0 +3:4/0 = 0 +3:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:4/0/physics_layer_0/angular_velocity = 0.0 +4:4/0 = 0 +4:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:4/0/physics_layer_0/angular_velocity = 0.0 +5:4/0 = 0 +5:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:4/0/physics_layer_0/angular_velocity = 0.0 +6:4/0 = 0 +6:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:4/0/physics_layer_0/angular_velocity = 0.0 +7:4/0 = 0 +7:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:4/0/physics_layer_0/angular_velocity = 0.0 +8:4/0 = 0 +8:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:4/0/physics_layer_0/angular_velocity = 0.0 +9:4/0 = 0 +9:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:4/0/physics_layer_0/angular_velocity = 0.0 +10:4/0 = 0 +10:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:4/0/physics_layer_0/angular_velocity = 0.0 +11:4/0 = 0 +11:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:4/0/physics_layer_0/angular_velocity = 0.0 +12:4/0 = 0 +12:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:4/0/physics_layer_0/angular_velocity = 0.0 +13:4/0 = 0 +13:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:4/0/physics_layer_0/angular_velocity = 0.0 +14:4/0 = 0 +14:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:4/0/physics_layer_0/angular_velocity = 0.0 +15:4/0 = 0 +15:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:4/0/physics_layer_0/angular_velocity = 0.0 +16:4/0 = 0 +16:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:4/0/physics_layer_0/angular_velocity = 0.0 +17:4/0 = 0 +17:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:4/0/physics_layer_0/angular_velocity = 0.0 +18:4/0 = 0 +18:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:4/0/physics_layer_0/angular_velocity = 0.0 +19:4/0 = 0 +19:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:4/0/physics_layer_0/angular_velocity = 0.0 +20:4/0 = 0 +20:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:4/0/physics_layer_0/angular_velocity = 0.0 +21:4/0 = 0 +21:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:4/0/physics_layer_0/angular_velocity = 0.0 +22:4/0 = 0 +22:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:4/0/physics_layer_0/angular_velocity = 0.0 +23:4/0 = 0 +23:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:4/0/physics_layer_0/angular_velocity = 0.0 +24:4/0 = 0 +24:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:4/0/physics_layer_0/angular_velocity = 0.0 +25:4/0 = 0 +25:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:4/0/physics_layer_0/angular_velocity = 0.0 +26:4/0 = 0 +26:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:4/0/physics_layer_0/angular_velocity = 0.0 +27:4/0 = 0 +27:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:4/0/physics_layer_0/angular_velocity = 0.0 +28:4/0 = 0 +28:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:4/0/physics_layer_0/angular_velocity = 0.0 +29:4/0 = 0 +29:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:4/0/physics_layer_0/angular_velocity = 0.0 +30:4/0 = 0 +30:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:4/0/physics_layer_0/angular_velocity = 0.0 +31:4/0 = 0 +31:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:4/0/physics_layer_0/angular_velocity = 0.0 +32:4/0 = 0 +32:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:4/0/physics_layer_0/angular_velocity = 0.0 +33:4/0 = 0 +33:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:4/0/physics_layer_0/angular_velocity = 0.0 +34:4/0 = 0 +34:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:4/0/physics_layer_0/angular_velocity = 0.0 +35:4/0 = 0 +35:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:4/0/physics_layer_0/angular_velocity = 0.0 +36:4/0 = 0 +36:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:4/0/physics_layer_0/angular_velocity = 0.0 +37:4/0 = 0 +37:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:4/0/physics_layer_0/angular_velocity = 0.0 +38:4/0 = 0 +38:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:4/0/physics_layer_0/angular_velocity = 0.0 +39:4/0 = 0 +39:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:4/0/physics_layer_0/angular_velocity = 0.0 +40:4/0 = 0 +40:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:4/0/physics_layer_0/angular_velocity = 0.0 +41:4/0 = 0 +41:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:4/0/physics_layer_0/angular_velocity = 0.0 +42:4/0 = 0 +42:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:4/0/physics_layer_0/angular_velocity = 0.0 +43:4/0 = 0 +43:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:4/0/physics_layer_0/angular_velocity = 0.0 +44:4/0 = 0 +44:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:4/0/physics_layer_0/angular_velocity = 0.0 +45:4/0 = 0 +45:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:4/0/physics_layer_0/angular_velocity = 0.0 +46:4/0 = 0 +46:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:4/0/physics_layer_0/angular_velocity = 0.0 +47:4/0 = 0 +47:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:4/0/physics_layer_0/angular_velocity = 0.0 +48:4/0 = 0 +48:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:4/0/physics_layer_0/angular_velocity = 0.0 +0:5/0 = 0 +0:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:5/0/physics_layer_0/angular_velocity = 0.0 +1:5/0 = 0 +1:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:5/0/physics_layer_0/angular_velocity = 0.0 +2:5/0 = 0 +2:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:5/0/physics_layer_0/angular_velocity = 0.0 +3:5/0 = 0 +3:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:5/0/physics_layer_0/angular_velocity = 0.0 +4:5/0 = 0 +4:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:5/0/physics_layer_0/angular_velocity = 0.0 +5:5/0 = 0 +5:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:5/0/physics_layer_0/angular_velocity = 0.0 +6:5/0 = 0 +6:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:5/0/physics_layer_0/angular_velocity = 0.0 +7:5/0 = 0 +7:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:5/0/physics_layer_0/angular_velocity = 0.0 +8:5/0 = 0 +8:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:5/0/physics_layer_0/angular_velocity = 0.0 +9:5/0 = 0 +9:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:5/0/physics_layer_0/angular_velocity = 0.0 +10:5/0 = 0 +10:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:5/0/physics_layer_0/angular_velocity = 0.0 +11:5/0 = 0 +11:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:5/0/physics_layer_0/angular_velocity = 0.0 +12:5/0 = 0 +12:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:5/0/physics_layer_0/angular_velocity = 0.0 +13:5/0 = 0 +13:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:5/0/physics_layer_0/angular_velocity = 0.0 +14:5/0 = 0 +14:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:5/0/physics_layer_0/angular_velocity = 0.0 +15:5/0 = 0 +15:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:5/0/physics_layer_0/angular_velocity = 0.0 +16:5/0 = 0 +16:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:5/0/physics_layer_0/angular_velocity = 0.0 +17:5/0 = 0 +17:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:5/0/physics_layer_0/angular_velocity = 0.0 +18:5/0 = 0 +18:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:5/0/physics_layer_0/angular_velocity = 0.0 +19:5/0 = 0 +19:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:5/0/physics_layer_0/angular_velocity = 0.0 +20:5/0 = 0 +20:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:5/0/physics_layer_0/angular_velocity = 0.0 +21:5/0 = 0 +21:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:5/0/physics_layer_0/angular_velocity = 0.0 +22:5/0 = 0 +22:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:5/0/physics_layer_0/angular_velocity = 0.0 +23:5/0 = 0 +23:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:5/0/physics_layer_0/angular_velocity = 0.0 +24:5/0 = 0 +24:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:5/0/physics_layer_0/angular_velocity = 0.0 +25:5/0 = 0 +25:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:5/0/physics_layer_0/angular_velocity = 0.0 +26:5/0 = 0 +26:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:5/0/physics_layer_0/angular_velocity = 0.0 +27:5/0 = 0 +27:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:5/0/physics_layer_0/angular_velocity = 0.0 +28:5/0 = 0 +28:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:5/0/physics_layer_0/angular_velocity = 0.0 +29:5/0 = 0 +29:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:5/0/physics_layer_0/angular_velocity = 0.0 +30:5/0 = 0 +30:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:5/0/physics_layer_0/angular_velocity = 0.0 +31:5/0 = 0 +31:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:5/0/physics_layer_0/angular_velocity = 0.0 +32:5/0 = 0 +32:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:5/0/physics_layer_0/angular_velocity = 0.0 +33:5/0 = 0 +33:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:5/0/physics_layer_0/angular_velocity = 0.0 +34:5/0 = 0 +34:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:5/0/physics_layer_0/angular_velocity = 0.0 +35:5/0 = 0 +35:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:5/0/physics_layer_0/angular_velocity = 0.0 +36:5/0 = 0 +36:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:5/0/physics_layer_0/angular_velocity = 0.0 +37:5/0 = 0 +37:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:5/0/physics_layer_0/angular_velocity = 0.0 +38:5/0 = 0 +38:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:5/0/physics_layer_0/angular_velocity = 0.0 +39:5/0 = 0 +39:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:5/0/physics_layer_0/angular_velocity = 0.0 +40:5/0 = 0 +40:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:5/0/physics_layer_0/angular_velocity = 0.0 +41:5/0 = 0 +41:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:5/0/physics_layer_0/angular_velocity = 0.0 +42:5/0 = 0 +42:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:5/0/physics_layer_0/angular_velocity = 0.0 +43:5/0 = 0 +43:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:5/0/physics_layer_0/angular_velocity = 0.0 +44:5/0 = 0 +44:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:5/0/physics_layer_0/angular_velocity = 0.0 +45:5/0 = 0 +45:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:5/0/physics_layer_0/angular_velocity = 0.0 +46:5/0 = 0 +46:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:5/0/physics_layer_0/angular_velocity = 0.0 +47:5/0 = 0 +47:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:5/0/physics_layer_0/angular_velocity = 0.0 +48:5/0 = 0 +48:5/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:5/0/physics_layer_0/angular_velocity = 0.0 +0:6/0 = 0 +0:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:6/0/physics_layer_0/angular_velocity = 0.0 +1:6/0 = 0 +1:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:6/0/physics_layer_0/angular_velocity = 0.0 +2:6/0 = 0 +2:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:6/0/physics_layer_0/angular_velocity = 0.0 +3:6/0 = 0 +3:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:6/0/physics_layer_0/angular_velocity = 0.0 +4:6/0 = 0 +4:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:6/0/physics_layer_0/angular_velocity = 0.0 +5:6/0 = 0 +5:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:6/0/physics_layer_0/angular_velocity = 0.0 +6:6/0 = 0 +6:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:6/0/physics_layer_0/angular_velocity = 0.0 +7:6/0 = 0 +7:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:6/0/physics_layer_0/angular_velocity = 0.0 +8:6/0 = 0 +8:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:6/0/physics_layer_0/angular_velocity = 0.0 +9:6/0 = 0 +9:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:6/0/physics_layer_0/angular_velocity = 0.0 +10:6/0 = 0 +10:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:6/0/physics_layer_0/angular_velocity = 0.0 +11:6/0 = 0 +11:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:6/0/physics_layer_0/angular_velocity = 0.0 +12:6/0 = 0 +12:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:6/0/physics_layer_0/angular_velocity = 0.0 +13:6/0 = 0 +13:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:6/0/physics_layer_0/angular_velocity = 0.0 +14:6/0 = 0 +14:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:6/0/physics_layer_0/angular_velocity = 0.0 +15:6/0 = 0 +15:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:6/0/physics_layer_0/angular_velocity = 0.0 +16:6/0 = 0 +16:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:6/0/physics_layer_0/angular_velocity = 0.0 +17:6/0 = 0 +17:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:6/0/physics_layer_0/angular_velocity = 0.0 +18:6/0 = 0 +18:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:6/0/physics_layer_0/angular_velocity = 0.0 +19:6/0 = 0 +19:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:6/0/physics_layer_0/angular_velocity = 0.0 +20:6/0 = 0 +20:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:6/0/physics_layer_0/angular_velocity = 0.0 +21:6/0 = 0 +21:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:6/0/physics_layer_0/angular_velocity = 0.0 +22:6/0 = 0 +22:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:6/0/physics_layer_0/angular_velocity = 0.0 +23:6/0 = 0 +23:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:6/0/physics_layer_0/angular_velocity = 0.0 +24:6/0 = 0 +24:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:6/0/physics_layer_0/angular_velocity = 0.0 +25:6/0 = 0 +25:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:6/0/physics_layer_0/angular_velocity = 0.0 +26:6/0 = 0 +26:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:6/0/physics_layer_0/angular_velocity = 0.0 +27:6/0 = 0 +27:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:6/0/physics_layer_0/angular_velocity = 0.0 +28:6/0 = 0 +28:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:6/0/physics_layer_0/angular_velocity = 0.0 +29:6/0 = 0 +29:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:6/0/physics_layer_0/angular_velocity = 0.0 +30:6/0 = 0 +30:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:6/0/physics_layer_0/angular_velocity = 0.0 +31:6/0 = 0 +31:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:6/0/physics_layer_0/angular_velocity = 0.0 +32:6/0 = 0 +32:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:6/0/physics_layer_0/angular_velocity = 0.0 +33:6/0 = 0 +33:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:6/0/physics_layer_0/angular_velocity = 0.0 +34:6/0 = 0 +34:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:6/0/physics_layer_0/angular_velocity = 0.0 +35:6/0 = 0 +35:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:6/0/physics_layer_0/angular_velocity = 0.0 +36:6/0 = 0 +36:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:6/0/physics_layer_0/angular_velocity = 0.0 +37:6/0 = 0 +37:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:6/0/physics_layer_0/angular_velocity = 0.0 +38:6/0 = 0 +38:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:6/0/physics_layer_0/angular_velocity = 0.0 +39:6/0 = 0 +39:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:6/0/physics_layer_0/angular_velocity = 0.0 +40:6/0 = 0 +40:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:6/0/physics_layer_0/angular_velocity = 0.0 +41:6/0 = 0 +41:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:6/0/physics_layer_0/angular_velocity = 0.0 +42:6/0 = 0 +42:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:6/0/physics_layer_0/angular_velocity = 0.0 +43:6/0 = 0 +43:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:6/0/physics_layer_0/angular_velocity = 0.0 +44:6/0 = 0 +44:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:6/0/physics_layer_0/angular_velocity = 0.0 +45:6/0 = 0 +45:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:6/0/physics_layer_0/angular_velocity = 0.0 +46:6/0 = 0 +46:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:6/0/physics_layer_0/angular_velocity = 0.0 +47:6/0 = 0 +47:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:6/0/physics_layer_0/angular_velocity = 0.0 +48:6/0 = 0 +48:6/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:6/0/physics_layer_0/angular_velocity = 0.0 +0:7/0 = 0 +0:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:7/0/physics_layer_0/angular_velocity = 0.0 +1:7/0 = 0 +1:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:7/0/physics_layer_0/angular_velocity = 0.0 +2:7/0 = 0 +2:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:7/0/physics_layer_0/angular_velocity = 0.0 +3:7/0 = 0 +3:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:7/0/physics_layer_0/angular_velocity = 0.0 +4:7/0 = 0 +4:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:7/0/physics_layer_0/angular_velocity = 0.0 +5:7/0 = 0 +5:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:7/0/physics_layer_0/angular_velocity = 0.0 +6:7/0 = 0 +6:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:7/0/physics_layer_0/angular_velocity = 0.0 +7:7/0 = 0 +7:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:7/0/physics_layer_0/angular_velocity = 0.0 +8:7/0 = 0 +8:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:7/0/physics_layer_0/angular_velocity = 0.0 +9:7/0 = 0 +9:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:7/0/physics_layer_0/angular_velocity = 0.0 +10:7/0 = 0 +10:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:7/0/physics_layer_0/angular_velocity = 0.0 +11:7/0 = 0 +11:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:7/0/physics_layer_0/angular_velocity = 0.0 +12:7/0 = 0 +12:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:7/0/physics_layer_0/angular_velocity = 0.0 +13:7/0 = 0 +13:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:7/0/physics_layer_0/angular_velocity = 0.0 +14:7/0 = 0 +14:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:7/0/physics_layer_0/angular_velocity = 0.0 +15:7/0 = 0 +15:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:7/0/physics_layer_0/angular_velocity = 0.0 +16:7/0 = 0 +16:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:7/0/physics_layer_0/angular_velocity = 0.0 +17:7/0 = 0 +17:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:7/0/physics_layer_0/angular_velocity = 0.0 +18:7/0 = 0 +18:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:7/0/physics_layer_0/angular_velocity = 0.0 +19:7/0 = 0 +19:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:7/0/physics_layer_0/angular_velocity = 0.0 +20:7/0 = 0 +20:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:7/0/physics_layer_0/angular_velocity = 0.0 +21:7/0 = 0 +21:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:7/0/physics_layer_0/angular_velocity = 0.0 +22:7/0 = 0 +22:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:7/0/physics_layer_0/angular_velocity = 0.0 +23:7/0 = 0 +23:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:7/0/physics_layer_0/angular_velocity = 0.0 +24:7/0 = 0 +24:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:7/0/physics_layer_0/angular_velocity = 0.0 +25:7/0 = 0 +25:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:7/0/physics_layer_0/angular_velocity = 0.0 +26:7/0 = 0 +26:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:7/0/physics_layer_0/angular_velocity = 0.0 +27:7/0 = 0 +27:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:7/0/physics_layer_0/angular_velocity = 0.0 +28:7/0 = 0 +28:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:7/0/physics_layer_0/angular_velocity = 0.0 +29:7/0 = 0 +29:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:7/0/physics_layer_0/angular_velocity = 0.0 +30:7/0 = 0 +30:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:7/0/physics_layer_0/angular_velocity = 0.0 +31:7/0 = 0 +31:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:7/0/physics_layer_0/angular_velocity = 0.0 +32:7/0 = 0 +32:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:7/0/physics_layer_0/angular_velocity = 0.0 +33:7/0 = 0 +33:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:7/0/physics_layer_0/angular_velocity = 0.0 +34:7/0 = 0 +34:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:7/0/physics_layer_0/angular_velocity = 0.0 +35:7/0 = 0 +35:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:7/0/physics_layer_0/angular_velocity = 0.0 +36:7/0 = 0 +36:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:7/0/physics_layer_0/angular_velocity = 0.0 +37:7/0 = 0 +37:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:7/0/physics_layer_0/angular_velocity = 0.0 +38:7/0 = 0 +38:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:7/0/physics_layer_0/angular_velocity = 0.0 +39:7/0 = 0 +39:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:7/0/physics_layer_0/angular_velocity = 0.0 +40:7/0 = 0 +40:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:7/0/physics_layer_0/angular_velocity = 0.0 +41:7/0 = 0 +41:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:7/0/physics_layer_0/angular_velocity = 0.0 +42:7/0 = 0 +42:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:7/0/physics_layer_0/angular_velocity = 0.0 +43:7/0 = 0 +43:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:7/0/physics_layer_0/angular_velocity = 0.0 +44:7/0 = 0 +44:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:7/0/physics_layer_0/angular_velocity = 0.0 +45:7/0 = 0 +45:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:7/0/physics_layer_0/angular_velocity = 0.0 +46:7/0 = 0 +46:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:7/0/physics_layer_0/angular_velocity = 0.0 +47:7/0 = 0 +47:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:7/0/physics_layer_0/angular_velocity = 0.0 +48:7/0 = 0 +48:7/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:7/0/physics_layer_0/angular_velocity = 0.0 +0:8/0 = 0 +0:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:8/0/physics_layer_0/angular_velocity = 0.0 +1:8/0 = 0 +1:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:8/0/physics_layer_0/angular_velocity = 0.0 +2:8/0 = 0 +2:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:8/0/physics_layer_0/angular_velocity = 0.0 +3:8/0 = 0 +3:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:8/0/physics_layer_0/angular_velocity = 0.0 +4:8/0 = 0 +4:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:8/0/physics_layer_0/angular_velocity = 0.0 +5:8/0 = 0 +5:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:8/0/physics_layer_0/angular_velocity = 0.0 +6:8/0 = 0 +6:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:8/0/physics_layer_0/angular_velocity = 0.0 +7:8/0 = 0 +7:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:8/0/physics_layer_0/angular_velocity = 0.0 +8:8/0 = 0 +8:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:8/0/physics_layer_0/angular_velocity = 0.0 +9:8/0 = 0 +9:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:8/0/physics_layer_0/angular_velocity = 0.0 +10:8/0 = 0 +10:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:8/0/physics_layer_0/angular_velocity = 0.0 +11:8/0 = 0 +11:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:8/0/physics_layer_0/angular_velocity = 0.0 +12:8/0 = 0 +12:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:8/0/physics_layer_0/angular_velocity = 0.0 +13:8/0 = 0 +13:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:8/0/physics_layer_0/angular_velocity = 0.0 +14:8/0 = 0 +14:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:8/0/physics_layer_0/angular_velocity = 0.0 +15:8/0 = 0 +15:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:8/0/physics_layer_0/angular_velocity = 0.0 +16:8/0 = 0 +16:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:8/0/physics_layer_0/angular_velocity = 0.0 +17:8/0 = 0 +17:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:8/0/physics_layer_0/angular_velocity = 0.0 +18:8/0 = 0 +18:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:8/0/physics_layer_0/angular_velocity = 0.0 +19:8/0 = 0 +19:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:8/0/physics_layer_0/angular_velocity = 0.0 +20:8/0 = 0 +20:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:8/0/physics_layer_0/angular_velocity = 0.0 +21:8/0 = 0 +21:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:8/0/physics_layer_0/angular_velocity = 0.0 +22:8/0 = 0 +22:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:8/0/physics_layer_0/angular_velocity = 0.0 +23:8/0 = 0 +23:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:8/0/physics_layer_0/angular_velocity = 0.0 +24:8/0 = 0 +24:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:8/0/physics_layer_0/angular_velocity = 0.0 +25:8/0 = 0 +25:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:8/0/physics_layer_0/angular_velocity = 0.0 +26:8/0 = 0 +26:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:8/0/physics_layer_0/angular_velocity = 0.0 +27:8/0 = 0 +27:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:8/0/physics_layer_0/angular_velocity = 0.0 +28:8/0 = 0 +28:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:8/0/physics_layer_0/angular_velocity = 0.0 +29:8/0 = 0 +29:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:8/0/physics_layer_0/angular_velocity = 0.0 +30:8/0 = 0 +30:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:8/0/physics_layer_0/angular_velocity = 0.0 +31:8/0 = 0 +31:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:8/0/physics_layer_0/angular_velocity = 0.0 +32:8/0 = 0 +32:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:8/0/physics_layer_0/angular_velocity = 0.0 +33:8/0 = 0 +33:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:8/0/physics_layer_0/angular_velocity = 0.0 +34:8/0 = 0 +34:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:8/0/physics_layer_0/angular_velocity = 0.0 +35:8/0 = 0 +35:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:8/0/physics_layer_0/angular_velocity = 0.0 +36:8/0 = 0 +36:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:8/0/physics_layer_0/angular_velocity = 0.0 +37:8/0 = 0 +37:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:8/0/physics_layer_0/angular_velocity = 0.0 +38:8/0 = 0 +38:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:8/0/physics_layer_0/angular_velocity = 0.0 +39:8/0 = 0 +39:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:8/0/physics_layer_0/angular_velocity = 0.0 +40:8/0 = 0 +40:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:8/0/physics_layer_0/angular_velocity = 0.0 +41:8/0 = 0 +41:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:8/0/physics_layer_0/angular_velocity = 0.0 +42:8/0 = 0 +42:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:8/0/physics_layer_0/angular_velocity = 0.0 +43:8/0 = 0 +43:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:8/0/physics_layer_0/angular_velocity = 0.0 +44:8/0 = 0 +44:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:8/0/physics_layer_0/angular_velocity = 0.0 +45:8/0 = 0 +45:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:8/0/physics_layer_0/angular_velocity = 0.0 +46:8/0 = 0 +46:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:8/0/physics_layer_0/angular_velocity = 0.0 +47:8/0 = 0 +47:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:8/0/physics_layer_0/angular_velocity = 0.0 +48:8/0 = 0 +48:8/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:8/0/physics_layer_0/angular_velocity = 0.0 +0:9/0 = 0 +0:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:9/0/physics_layer_0/angular_velocity = 0.0 +1:9/0 = 0 +1:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:9/0/physics_layer_0/angular_velocity = 0.0 +2:9/0 = 0 +2:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:9/0/physics_layer_0/angular_velocity = 0.0 +3:9/0 = 0 +3:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:9/0/physics_layer_0/angular_velocity = 0.0 +4:9/0 = 0 +4:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:9/0/physics_layer_0/angular_velocity = 0.0 +5:9/0 = 0 +5:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:9/0/physics_layer_0/angular_velocity = 0.0 +6:9/0 = 0 +6:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:9/0/physics_layer_0/angular_velocity = 0.0 +7:9/0 = 0 +7:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:9/0/physics_layer_0/angular_velocity = 0.0 +8:9/0 = 0 +8:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:9/0/physics_layer_0/angular_velocity = 0.0 +9:9/0 = 0 +9:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:9/0/physics_layer_0/angular_velocity = 0.0 +10:9/0 = 0 +10:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:9/0/physics_layer_0/angular_velocity = 0.0 +11:9/0 = 0 +11:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:9/0/physics_layer_0/angular_velocity = 0.0 +12:9/0 = 0 +12:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:9/0/physics_layer_0/angular_velocity = 0.0 +13:9/0 = 0 +13:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:9/0/physics_layer_0/angular_velocity = 0.0 +14:9/0 = 0 +14:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:9/0/physics_layer_0/angular_velocity = 0.0 +15:9/0 = 0 +15:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:9/0/physics_layer_0/angular_velocity = 0.0 +16:9/0 = 0 +16:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:9/0/physics_layer_0/angular_velocity = 0.0 +17:9/0 = 0 +17:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:9/0/physics_layer_0/angular_velocity = 0.0 +18:9/0 = 0 +18:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:9/0/physics_layer_0/angular_velocity = 0.0 +19:9/0 = 0 +19:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:9/0/physics_layer_0/angular_velocity = 0.0 +20:9/0 = 0 +20:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:9/0/physics_layer_0/angular_velocity = 0.0 +21:9/0 = 0 +21:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:9/0/physics_layer_0/angular_velocity = 0.0 +22:9/0 = 0 +22:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:9/0/physics_layer_0/angular_velocity = 0.0 +23:9/0 = 0 +23:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:9/0/physics_layer_0/angular_velocity = 0.0 +24:9/0 = 0 +24:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:9/0/physics_layer_0/angular_velocity = 0.0 +25:9/0 = 0 +25:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:9/0/physics_layer_0/angular_velocity = 0.0 +26:9/0 = 0 +26:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:9/0/physics_layer_0/angular_velocity = 0.0 +27:9/0 = 0 +27:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:9/0/physics_layer_0/angular_velocity = 0.0 +28:9/0 = 0 +28:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:9/0/physics_layer_0/angular_velocity = 0.0 +29:9/0 = 0 +29:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:9/0/physics_layer_0/angular_velocity = 0.0 +30:9/0 = 0 +30:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:9/0/physics_layer_0/angular_velocity = 0.0 +31:9/0 = 0 +31:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:9/0/physics_layer_0/angular_velocity = 0.0 +32:9/0 = 0 +32:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:9/0/physics_layer_0/angular_velocity = 0.0 +33:9/0 = 0 +33:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:9/0/physics_layer_0/angular_velocity = 0.0 +34:9/0 = 0 +34:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:9/0/physics_layer_0/angular_velocity = 0.0 +35:9/0 = 0 +35:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:9/0/physics_layer_0/angular_velocity = 0.0 +36:9/0 = 0 +36:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:9/0/physics_layer_0/angular_velocity = 0.0 +37:9/0 = 0 +37:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:9/0/physics_layer_0/angular_velocity = 0.0 +38:9/0 = 0 +38:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:9/0/physics_layer_0/angular_velocity = 0.0 +39:9/0 = 0 +39:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:9/0/physics_layer_0/angular_velocity = 0.0 +40:9/0 = 0 +40:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:9/0/physics_layer_0/angular_velocity = 0.0 +41:9/0 = 0 +41:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:9/0/physics_layer_0/angular_velocity = 0.0 +42:9/0 = 0 +42:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:9/0/physics_layer_0/angular_velocity = 0.0 +43:9/0 = 0 +43:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:9/0/physics_layer_0/angular_velocity = 0.0 +44:9/0 = 0 +44:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:9/0/physics_layer_0/angular_velocity = 0.0 +45:9/0 = 0 +45:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:9/0/physics_layer_0/angular_velocity = 0.0 +46:9/0 = 0 +46:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:9/0/physics_layer_0/angular_velocity = 0.0 +47:9/0 = 0 +47:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:9/0/physics_layer_0/angular_velocity = 0.0 +48:9/0 = 0 +48:9/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:9/0/physics_layer_0/angular_velocity = 0.0 +0:10/0 = 0 +0:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:10/0/physics_layer_0/angular_velocity = 0.0 +1:10/0 = 0 +1:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:10/0/physics_layer_0/angular_velocity = 0.0 +2:10/0 = 0 +2:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:10/0/physics_layer_0/angular_velocity = 0.0 +3:10/0 = 0 +3:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:10/0/physics_layer_0/angular_velocity = 0.0 +4:10/0 = 0 +4:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:10/0/physics_layer_0/angular_velocity = 0.0 +5:10/0 = 0 +5:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:10/0/physics_layer_0/angular_velocity = 0.0 +6:10/0 = 0 +6:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:10/0/physics_layer_0/angular_velocity = 0.0 +7:10/0 = 0 +7:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:10/0/physics_layer_0/angular_velocity = 0.0 +8:10/0 = 0 +8:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:10/0/physics_layer_0/angular_velocity = 0.0 +9:10/0 = 0 +9:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:10/0/physics_layer_0/angular_velocity = 0.0 +10:10/0 = 0 +10:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:10/0/physics_layer_0/angular_velocity = 0.0 +11:10/0 = 0 +11:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:10/0/physics_layer_0/angular_velocity = 0.0 +12:10/0 = 0 +12:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:10/0/physics_layer_0/angular_velocity = 0.0 +13:10/0 = 0 +13:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:10/0/physics_layer_0/angular_velocity = 0.0 +14:10/0 = 0 +14:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:10/0/physics_layer_0/angular_velocity = 0.0 +15:10/0 = 0 +15:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:10/0/physics_layer_0/angular_velocity = 0.0 +16:10/0 = 0 +16:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:10/0/physics_layer_0/angular_velocity = 0.0 +17:10/0 = 0 +17:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:10/0/physics_layer_0/angular_velocity = 0.0 +18:10/0 = 0 +18:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:10/0/physics_layer_0/angular_velocity = 0.0 +19:10/0 = 0 +19:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:10/0/physics_layer_0/angular_velocity = 0.0 +20:10/0 = 0 +20:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:10/0/physics_layer_0/angular_velocity = 0.0 +21:10/0 = 0 +21:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:10/0/physics_layer_0/angular_velocity = 0.0 +22:10/0 = 0 +22:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:10/0/physics_layer_0/angular_velocity = 0.0 +23:10/0 = 0 +23:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:10/0/physics_layer_0/angular_velocity = 0.0 +24:10/0 = 0 +24:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:10/0/physics_layer_0/angular_velocity = 0.0 +25:10/0 = 0 +25:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:10/0/physics_layer_0/angular_velocity = 0.0 +26:10/0 = 0 +26:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:10/0/physics_layer_0/angular_velocity = 0.0 +27:10/0 = 0 +27:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:10/0/physics_layer_0/angular_velocity = 0.0 +28:10/0 = 0 +28:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:10/0/physics_layer_0/angular_velocity = 0.0 +29:10/0 = 0 +29:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:10/0/physics_layer_0/angular_velocity = 0.0 +30:10/0 = 0 +30:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:10/0/physics_layer_0/angular_velocity = 0.0 +31:10/0 = 0 +31:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:10/0/physics_layer_0/angular_velocity = 0.0 +32:10/0 = 0 +32:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:10/0/physics_layer_0/angular_velocity = 0.0 +33:10/0 = 0 +33:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:10/0/physics_layer_0/angular_velocity = 0.0 +34:10/0 = 0 +34:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:10/0/physics_layer_0/angular_velocity = 0.0 +35:10/0 = 0 +35:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:10/0/physics_layer_0/angular_velocity = 0.0 +36:10/0 = 0 +36:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:10/0/physics_layer_0/angular_velocity = 0.0 +37:10/0 = 0 +37:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:10/0/physics_layer_0/angular_velocity = 0.0 +38:10/0 = 0 +38:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:10/0/physics_layer_0/angular_velocity = 0.0 +39:10/0 = 0 +39:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:10/0/physics_layer_0/angular_velocity = 0.0 +40:10/0 = 0 +40:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:10/0/physics_layer_0/angular_velocity = 0.0 +41:10/0 = 0 +41:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:10/0/physics_layer_0/angular_velocity = 0.0 +42:10/0 = 0 +42:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:10/0/physics_layer_0/angular_velocity = 0.0 +43:10/0 = 0 +43:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:10/0/physics_layer_0/angular_velocity = 0.0 +44:10/0 = 0 +44:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:10/0/physics_layer_0/angular_velocity = 0.0 +45:10/0 = 0 +45:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:10/0/physics_layer_0/angular_velocity = 0.0 +46:10/0 = 0 +46:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:10/0/physics_layer_0/angular_velocity = 0.0 +47:10/0 = 0 +47:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:10/0/physics_layer_0/angular_velocity = 0.0 +48:10/0 = 0 +48:10/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:10/0/physics_layer_0/angular_velocity = 0.0 +0:11/0 = 0 +0:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:11/0/physics_layer_0/angular_velocity = 0.0 +1:11/0 = 0 +1:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:11/0/physics_layer_0/angular_velocity = 0.0 +2:11/0 = 0 +2:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:11/0/physics_layer_0/angular_velocity = 0.0 +3:11/0 = 0 +3:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:11/0/physics_layer_0/angular_velocity = 0.0 +4:11/0 = 0 +4:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:11/0/physics_layer_0/angular_velocity = 0.0 +5:11/0 = 0 +5:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:11/0/physics_layer_0/angular_velocity = 0.0 +6:11/0 = 0 +6:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:11/0/physics_layer_0/angular_velocity = 0.0 +7:11/0 = 0 +7:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:11/0/physics_layer_0/angular_velocity = 0.0 +8:11/0 = 0 +8:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:11/0/physics_layer_0/angular_velocity = 0.0 +9:11/0 = 0 +9:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:11/0/physics_layer_0/angular_velocity = 0.0 +10:11/0 = 0 +10:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:11/0/physics_layer_0/angular_velocity = 0.0 +11:11/0 = 0 +11:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:11/0/physics_layer_0/angular_velocity = 0.0 +12:11/0 = 0 +12:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:11/0/physics_layer_0/angular_velocity = 0.0 +13:11/0 = 0 +13:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:11/0/physics_layer_0/angular_velocity = 0.0 +14:11/0 = 0 +14:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:11/0/physics_layer_0/angular_velocity = 0.0 +15:11/0 = 0 +15:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:11/0/physics_layer_0/angular_velocity = 0.0 +16:11/0 = 0 +16:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:11/0/physics_layer_0/angular_velocity = 0.0 +17:11/0 = 0 +17:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:11/0/physics_layer_0/angular_velocity = 0.0 +18:11/0 = 0 +18:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:11/0/physics_layer_0/angular_velocity = 0.0 +19:11/0 = 0 +19:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:11/0/physics_layer_0/angular_velocity = 0.0 +20:11/0 = 0 +20:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:11/0/physics_layer_0/angular_velocity = 0.0 +21:11/0 = 0 +21:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:11/0/physics_layer_0/angular_velocity = 0.0 +22:11/0 = 0 +22:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:11/0/physics_layer_0/angular_velocity = 0.0 +23:11/0 = 0 +23:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:11/0/physics_layer_0/angular_velocity = 0.0 +24:11/0 = 0 +24:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:11/0/physics_layer_0/angular_velocity = 0.0 +25:11/0 = 0 +25:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:11/0/physics_layer_0/angular_velocity = 0.0 +26:11/0 = 0 +26:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:11/0/physics_layer_0/angular_velocity = 0.0 +27:11/0 = 0 +27:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:11/0/physics_layer_0/angular_velocity = 0.0 +28:11/0 = 0 +28:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:11/0/physics_layer_0/angular_velocity = 0.0 +29:11/0 = 0 +29:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:11/0/physics_layer_0/angular_velocity = 0.0 +30:11/0 = 0 +30:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:11/0/physics_layer_0/angular_velocity = 0.0 +31:11/0 = 0 +31:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:11/0/physics_layer_0/angular_velocity = 0.0 +32:11/0 = 0 +32:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:11/0/physics_layer_0/angular_velocity = 0.0 +33:11/0 = 0 +33:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:11/0/physics_layer_0/angular_velocity = 0.0 +34:11/0 = 0 +34:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:11/0/physics_layer_0/angular_velocity = 0.0 +35:11/0 = 0 +35:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:11/0/physics_layer_0/angular_velocity = 0.0 +36:11/0 = 0 +36:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:11/0/physics_layer_0/angular_velocity = 0.0 +37:11/0 = 0 +37:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:11/0/physics_layer_0/angular_velocity = 0.0 +38:11/0 = 0 +38:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:11/0/physics_layer_0/angular_velocity = 0.0 +39:11/0 = 0 +39:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:11/0/physics_layer_0/angular_velocity = 0.0 +40:11/0 = 0 +40:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:11/0/physics_layer_0/angular_velocity = 0.0 +41:11/0 = 0 +41:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:11/0/physics_layer_0/angular_velocity = 0.0 +42:11/0 = 0 +42:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:11/0/physics_layer_0/angular_velocity = 0.0 +43:11/0 = 0 +43:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:11/0/physics_layer_0/angular_velocity = 0.0 +44:11/0 = 0 +44:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:11/0/physics_layer_0/angular_velocity = 0.0 +45:11/0 = 0 +45:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:11/0/physics_layer_0/angular_velocity = 0.0 +46:11/0 = 0 +46:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:11/0/physics_layer_0/angular_velocity = 0.0 +47:11/0 = 0 +47:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:11/0/physics_layer_0/angular_velocity = 0.0 +48:11/0 = 0 +48:11/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:11/0/physics_layer_0/angular_velocity = 0.0 +0:12/0 = 0 +0:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:12/0/physics_layer_0/angular_velocity = 0.0 +1:12/0 = 0 +1:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:12/0/physics_layer_0/angular_velocity = 0.0 +2:12/0 = 0 +2:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:12/0/physics_layer_0/angular_velocity = 0.0 +3:12/0 = 0 +3:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:12/0/physics_layer_0/angular_velocity = 0.0 +4:12/0 = 0 +4:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:12/0/physics_layer_0/angular_velocity = 0.0 +5:12/0 = 0 +5:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:12/0/physics_layer_0/angular_velocity = 0.0 +6:12/0 = 0 +6:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:12/0/physics_layer_0/angular_velocity = 0.0 +7:12/0 = 0 +7:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:12/0/physics_layer_0/angular_velocity = 0.0 +8:12/0 = 0 +8:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:12/0/physics_layer_0/angular_velocity = 0.0 +9:12/0 = 0 +9:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:12/0/physics_layer_0/angular_velocity = 0.0 +10:12/0 = 0 +10:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:12/0/physics_layer_0/angular_velocity = 0.0 +11:12/0 = 0 +11:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:12/0/physics_layer_0/angular_velocity = 0.0 +12:12/0 = 0 +12:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:12/0/physics_layer_0/angular_velocity = 0.0 +13:12/0 = 0 +13:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:12/0/physics_layer_0/angular_velocity = 0.0 +14:12/0 = 0 +14:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:12/0/physics_layer_0/angular_velocity = 0.0 +15:12/0 = 0 +15:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:12/0/physics_layer_0/angular_velocity = 0.0 +16:12/0 = 0 +16:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:12/0/physics_layer_0/angular_velocity = 0.0 +17:12/0 = 0 +17:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:12/0/physics_layer_0/angular_velocity = 0.0 +18:12/0 = 0 +18:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:12/0/physics_layer_0/angular_velocity = 0.0 +19:12/0 = 0 +19:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:12/0/physics_layer_0/angular_velocity = 0.0 +20:12/0 = 0 +20:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:12/0/physics_layer_0/angular_velocity = 0.0 +21:12/0 = 0 +21:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:12/0/physics_layer_0/angular_velocity = 0.0 +22:12/0 = 0 +22:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:12/0/physics_layer_0/angular_velocity = 0.0 +23:12/0 = 0 +23:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:12/0/physics_layer_0/angular_velocity = 0.0 +24:12/0 = 0 +24:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:12/0/physics_layer_0/angular_velocity = 0.0 +25:12/0 = 0 +25:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:12/0/physics_layer_0/angular_velocity = 0.0 +26:12/0 = 0 +26:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:12/0/physics_layer_0/angular_velocity = 0.0 +27:12/0 = 0 +27:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:12/0/physics_layer_0/angular_velocity = 0.0 +28:12/0 = 0 +28:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:12/0/physics_layer_0/angular_velocity = 0.0 +29:12/0 = 0 +29:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:12/0/physics_layer_0/angular_velocity = 0.0 +30:12/0 = 0 +30:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:12/0/physics_layer_0/angular_velocity = 0.0 +31:12/0 = 0 +31:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:12/0/physics_layer_0/angular_velocity = 0.0 +32:12/0 = 0 +32:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:12/0/physics_layer_0/angular_velocity = 0.0 +33:12/0 = 0 +33:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:12/0/physics_layer_0/angular_velocity = 0.0 +34:12/0 = 0 +34:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:12/0/physics_layer_0/angular_velocity = 0.0 +35:12/0 = 0 +35:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:12/0/physics_layer_0/angular_velocity = 0.0 +36:12/0 = 0 +36:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:12/0/physics_layer_0/angular_velocity = 0.0 +37:12/0 = 0 +37:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:12/0/physics_layer_0/angular_velocity = 0.0 +38:12/0 = 0 +38:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:12/0/physics_layer_0/angular_velocity = 0.0 +39:12/0 = 0 +39:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:12/0/physics_layer_0/angular_velocity = 0.0 +40:12/0 = 0 +40:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:12/0/physics_layer_0/angular_velocity = 0.0 +41:12/0 = 0 +41:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:12/0/physics_layer_0/angular_velocity = 0.0 +42:12/0 = 0 +42:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:12/0/physics_layer_0/angular_velocity = 0.0 +43:12/0 = 0 +43:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:12/0/physics_layer_0/angular_velocity = 0.0 +44:12/0 = 0 +44:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:12/0/physics_layer_0/angular_velocity = 0.0 +45:12/0 = 0 +45:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:12/0/physics_layer_0/angular_velocity = 0.0 +46:12/0 = 0 +46:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:12/0/physics_layer_0/angular_velocity = 0.0 +47:12/0 = 0 +47:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:12/0/physics_layer_0/angular_velocity = 0.0 +48:12/0 = 0 +48:12/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:12/0/physics_layer_0/angular_velocity = 0.0 +0:13/0 = 0 +0:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:13/0/physics_layer_0/angular_velocity = 0.0 +1:13/0 = 0 +1:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:13/0/physics_layer_0/angular_velocity = 0.0 +2:13/0 = 0 +2:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:13/0/physics_layer_0/angular_velocity = 0.0 +3:13/0 = 0 +3:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:13/0/physics_layer_0/angular_velocity = 0.0 +4:13/0 = 0 +4:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:13/0/physics_layer_0/angular_velocity = 0.0 +5:13/0 = 0 +5:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:13/0/physics_layer_0/angular_velocity = 0.0 +6:13/0 = 0 +6:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:13/0/physics_layer_0/angular_velocity = 0.0 +7:13/0 = 0 +7:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:13/0/physics_layer_0/angular_velocity = 0.0 +8:13/0 = 0 +8:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:13/0/physics_layer_0/angular_velocity = 0.0 +9:13/0 = 0 +9:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:13/0/physics_layer_0/angular_velocity = 0.0 +10:13/0 = 0 +10:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:13/0/physics_layer_0/angular_velocity = 0.0 +11:13/0 = 0 +11:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:13/0/physics_layer_0/angular_velocity = 0.0 +12:13/0 = 0 +12:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:13/0/physics_layer_0/angular_velocity = 0.0 +13:13/0 = 0 +13:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:13/0/physics_layer_0/angular_velocity = 0.0 +14:13/0 = 0 +14:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:13/0/physics_layer_0/angular_velocity = 0.0 +15:13/0 = 0 +15:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:13/0/physics_layer_0/angular_velocity = 0.0 +16:13/0 = 0 +16:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:13/0/physics_layer_0/angular_velocity = 0.0 +17:13/0 = 0 +17:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:13/0/physics_layer_0/angular_velocity = 0.0 +18:13/0 = 0 +18:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:13/0/physics_layer_0/angular_velocity = 0.0 +19:13/0 = 0 +19:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:13/0/physics_layer_0/angular_velocity = 0.0 +20:13/0 = 0 +20:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:13/0/physics_layer_0/angular_velocity = 0.0 +21:13/0 = 0 +21:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:13/0/physics_layer_0/angular_velocity = 0.0 +22:13/0 = 0 +22:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:13/0/physics_layer_0/angular_velocity = 0.0 +23:13/0 = 0 +23:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:13/0/physics_layer_0/angular_velocity = 0.0 +24:13/0 = 0 +24:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:13/0/physics_layer_0/angular_velocity = 0.0 +25:13/0 = 0 +25:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:13/0/physics_layer_0/angular_velocity = 0.0 +26:13/0 = 0 +26:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:13/0/physics_layer_0/angular_velocity = 0.0 +27:13/0 = 0 +27:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:13/0/physics_layer_0/angular_velocity = 0.0 +28:13/0 = 0 +28:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:13/0/physics_layer_0/angular_velocity = 0.0 +29:13/0 = 0 +29:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:13/0/physics_layer_0/angular_velocity = 0.0 +30:13/0 = 0 +30:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:13/0/physics_layer_0/angular_velocity = 0.0 +31:13/0 = 0 +31:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:13/0/physics_layer_0/angular_velocity = 0.0 +32:13/0 = 0 +32:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:13/0/physics_layer_0/angular_velocity = 0.0 +33:13/0 = 0 +33:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:13/0/physics_layer_0/angular_velocity = 0.0 +34:13/0 = 0 +34:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:13/0/physics_layer_0/angular_velocity = 0.0 +35:13/0 = 0 +35:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:13/0/physics_layer_0/angular_velocity = 0.0 +36:13/0 = 0 +36:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:13/0/physics_layer_0/angular_velocity = 0.0 +37:13/0 = 0 +37:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:13/0/physics_layer_0/angular_velocity = 0.0 +38:13/0 = 0 +38:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:13/0/physics_layer_0/angular_velocity = 0.0 +39:13/0 = 0 +39:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:13/0/physics_layer_0/angular_velocity = 0.0 +40:13/0 = 0 +40:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:13/0/physics_layer_0/angular_velocity = 0.0 +41:13/0 = 0 +41:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:13/0/physics_layer_0/angular_velocity = 0.0 +42:13/0 = 0 +42:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:13/0/physics_layer_0/angular_velocity = 0.0 +43:13/0 = 0 +43:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:13/0/physics_layer_0/angular_velocity = 0.0 +44:13/0 = 0 +44:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:13/0/physics_layer_0/angular_velocity = 0.0 +45:13/0 = 0 +45:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:13/0/physics_layer_0/angular_velocity = 0.0 +46:13/0 = 0 +46:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:13/0/physics_layer_0/angular_velocity = 0.0 +47:13/0 = 0 +47:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:13/0/physics_layer_0/angular_velocity = 0.0 +48:13/0 = 0 +48:13/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:13/0/physics_layer_0/angular_velocity = 0.0 +0:14/0 = 0 +0:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:14/0/physics_layer_0/angular_velocity = 0.0 +1:14/0 = 0 +1:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:14/0/physics_layer_0/angular_velocity = 0.0 +2:14/0 = 0 +2:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:14/0/physics_layer_0/angular_velocity = 0.0 +3:14/0 = 0 +3:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:14/0/physics_layer_0/angular_velocity = 0.0 +4:14/0 = 0 +4:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:14/0/physics_layer_0/angular_velocity = 0.0 +5:14/0 = 0 +5:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:14/0/physics_layer_0/angular_velocity = 0.0 +6:14/0 = 0 +6:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:14/0/physics_layer_0/angular_velocity = 0.0 +7:14/0 = 0 +7:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:14/0/physics_layer_0/angular_velocity = 0.0 +8:14/0 = 0 +8:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:14/0/physics_layer_0/angular_velocity = 0.0 +9:14/0 = 0 +9:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:14/0/physics_layer_0/angular_velocity = 0.0 +10:14/0 = 0 +10:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:14/0/physics_layer_0/angular_velocity = 0.0 +11:14/0 = 0 +11:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:14/0/physics_layer_0/angular_velocity = 0.0 +12:14/0 = 0 +12:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:14/0/physics_layer_0/angular_velocity = 0.0 +13:14/0 = 0 +13:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:14/0/physics_layer_0/angular_velocity = 0.0 +14:14/0 = 0 +14:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:14/0/physics_layer_0/angular_velocity = 0.0 +15:14/0 = 0 +15:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:14/0/physics_layer_0/angular_velocity = 0.0 +16:14/0 = 0 +16:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:14/0/physics_layer_0/angular_velocity = 0.0 +17:14/0 = 0 +17:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:14/0/physics_layer_0/angular_velocity = 0.0 +18:14/0 = 0 +18:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:14/0/physics_layer_0/angular_velocity = 0.0 +19:14/0 = 0 +19:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:14/0/physics_layer_0/angular_velocity = 0.0 +20:14/0 = 0 +20:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:14/0/physics_layer_0/angular_velocity = 0.0 +21:14/0 = 0 +21:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:14/0/physics_layer_0/angular_velocity = 0.0 +22:14/0 = 0 +22:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:14/0/physics_layer_0/angular_velocity = 0.0 +23:14/0 = 0 +23:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:14/0/physics_layer_0/angular_velocity = 0.0 +24:14/0 = 0 +24:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:14/0/physics_layer_0/angular_velocity = 0.0 +25:14/0 = 0 +25:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:14/0/physics_layer_0/angular_velocity = 0.0 +26:14/0 = 0 +26:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:14/0/physics_layer_0/angular_velocity = 0.0 +27:14/0 = 0 +27:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:14/0/physics_layer_0/angular_velocity = 0.0 +28:14/0 = 0 +28:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:14/0/physics_layer_0/angular_velocity = 0.0 +29:14/0 = 0 +29:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:14/0/physics_layer_0/angular_velocity = 0.0 +30:14/0 = 0 +30:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:14/0/physics_layer_0/angular_velocity = 0.0 +31:14/0 = 0 +31:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:14/0/physics_layer_0/angular_velocity = 0.0 +32:14/0 = 0 +32:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:14/0/physics_layer_0/angular_velocity = 0.0 +33:14/0 = 0 +33:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:14/0/physics_layer_0/angular_velocity = 0.0 +34:14/0 = 0 +34:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:14/0/physics_layer_0/angular_velocity = 0.0 +35:14/0 = 0 +35:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:14/0/physics_layer_0/angular_velocity = 0.0 +36:14/0 = 0 +36:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:14/0/physics_layer_0/angular_velocity = 0.0 +37:14/0 = 0 +37:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:14/0/physics_layer_0/angular_velocity = 0.0 +38:14/0 = 0 +38:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:14/0/physics_layer_0/angular_velocity = 0.0 +39:14/0 = 0 +39:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:14/0/physics_layer_0/angular_velocity = 0.0 +40:14/0 = 0 +40:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:14/0/physics_layer_0/angular_velocity = 0.0 +41:14/0 = 0 +41:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:14/0/physics_layer_0/angular_velocity = 0.0 +42:14/0 = 0 +42:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:14/0/physics_layer_0/angular_velocity = 0.0 +43:14/0 = 0 +43:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:14/0/physics_layer_0/angular_velocity = 0.0 +44:14/0 = 0 +44:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:14/0/physics_layer_0/angular_velocity = 0.0 +45:14/0 = 0 +45:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:14/0/physics_layer_0/angular_velocity = 0.0 +46:14/0 = 0 +46:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:14/0/physics_layer_0/angular_velocity = 0.0 +47:14/0 = 0 +47:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:14/0/physics_layer_0/angular_velocity = 0.0 +48:14/0 = 0 +48:14/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:14/0/physics_layer_0/angular_velocity = 0.0 +0:15/0 = 0 +0:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:15/0/physics_layer_0/angular_velocity = 0.0 +1:15/0 = 0 +1:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:15/0/physics_layer_0/angular_velocity = 0.0 +2:15/0 = 0 +2:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:15/0/physics_layer_0/angular_velocity = 0.0 +3:15/0 = 0 +3:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:15/0/physics_layer_0/angular_velocity = 0.0 +4:15/0 = 0 +4:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:15/0/physics_layer_0/angular_velocity = 0.0 +5:15/0 = 0 +5:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:15/0/physics_layer_0/angular_velocity = 0.0 +6:15/0 = 0 +6:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:15/0/physics_layer_0/angular_velocity = 0.0 +7:15/0 = 0 +7:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:15/0/physics_layer_0/angular_velocity = 0.0 +8:15/0 = 0 +8:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:15/0/physics_layer_0/angular_velocity = 0.0 +9:15/0 = 0 +9:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:15/0/physics_layer_0/angular_velocity = 0.0 +10:15/0 = 0 +10:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:15/0/physics_layer_0/angular_velocity = 0.0 +11:15/0 = 0 +11:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:15/0/physics_layer_0/angular_velocity = 0.0 +12:15/0 = 0 +12:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:15/0/physics_layer_0/angular_velocity = 0.0 +13:15/0 = 0 +13:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:15/0/physics_layer_0/angular_velocity = 0.0 +14:15/0 = 0 +14:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:15/0/physics_layer_0/angular_velocity = 0.0 +15:15/0 = 0 +15:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:15/0/physics_layer_0/angular_velocity = 0.0 +16:15/0 = 0 +16:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:15/0/physics_layer_0/angular_velocity = 0.0 +17:15/0 = 0 +17:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:15/0/physics_layer_0/angular_velocity = 0.0 +18:15/0 = 0 +18:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:15/0/physics_layer_0/angular_velocity = 0.0 +19:15/0 = 0 +19:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:15/0/physics_layer_0/angular_velocity = 0.0 +20:15/0 = 0 +20:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:15/0/physics_layer_0/angular_velocity = 0.0 +21:15/0 = 0 +21:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:15/0/physics_layer_0/angular_velocity = 0.0 +22:15/0 = 0 +22:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:15/0/physics_layer_0/angular_velocity = 0.0 +23:15/0 = 0 +23:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:15/0/physics_layer_0/angular_velocity = 0.0 +24:15/0 = 0 +24:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:15/0/physics_layer_0/angular_velocity = 0.0 +25:15/0 = 0 +25:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:15/0/physics_layer_0/angular_velocity = 0.0 +26:15/0 = 0 +26:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:15/0/physics_layer_0/angular_velocity = 0.0 +27:15/0 = 0 +27:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:15/0/physics_layer_0/angular_velocity = 0.0 +28:15/0 = 0 +28:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:15/0/physics_layer_0/angular_velocity = 0.0 +29:15/0 = 0 +29:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:15/0/physics_layer_0/angular_velocity = 0.0 +30:15/0 = 0 +30:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:15/0/physics_layer_0/angular_velocity = 0.0 +31:15/0 = 0 +31:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:15/0/physics_layer_0/angular_velocity = 0.0 +32:15/0 = 0 +32:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:15/0/physics_layer_0/angular_velocity = 0.0 +33:15/0 = 0 +33:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:15/0/physics_layer_0/angular_velocity = 0.0 +34:15/0 = 0 +34:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:15/0/physics_layer_0/angular_velocity = 0.0 +35:15/0 = 0 +35:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:15/0/physics_layer_0/angular_velocity = 0.0 +36:15/0 = 0 +36:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:15/0/physics_layer_0/angular_velocity = 0.0 +37:15/0 = 0 +37:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:15/0/physics_layer_0/angular_velocity = 0.0 +38:15/0 = 0 +38:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:15/0/physics_layer_0/angular_velocity = 0.0 +39:15/0 = 0 +39:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:15/0/physics_layer_0/angular_velocity = 0.0 +40:15/0 = 0 +40:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:15/0/physics_layer_0/angular_velocity = 0.0 +41:15/0 = 0 +41:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:15/0/physics_layer_0/angular_velocity = 0.0 +42:15/0 = 0 +42:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:15/0/physics_layer_0/angular_velocity = 0.0 +43:15/0 = 0 +43:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:15/0/physics_layer_0/angular_velocity = 0.0 +44:15/0 = 0 +44:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:15/0/physics_layer_0/angular_velocity = 0.0 +45:15/0 = 0 +45:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:15/0/physics_layer_0/angular_velocity = 0.0 +46:15/0 = 0 +46:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:15/0/physics_layer_0/angular_velocity = 0.0 +47:15/0 = 0 +47:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:15/0/physics_layer_0/angular_velocity = 0.0 +48:15/0 = 0 +48:15/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:15/0/physics_layer_0/angular_velocity = 0.0 +0:16/0 = 0 +0:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:16/0/physics_layer_0/angular_velocity = 0.0 +1:16/0 = 0 +1:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:16/0/physics_layer_0/angular_velocity = 0.0 +2:16/0 = 0 +2:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:16/0/physics_layer_0/angular_velocity = 0.0 +3:16/0 = 0 +3:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:16/0/physics_layer_0/angular_velocity = 0.0 +4:16/0 = 0 +4:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:16/0/physics_layer_0/angular_velocity = 0.0 +5:16/0 = 0 +5:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:16/0/physics_layer_0/angular_velocity = 0.0 +6:16/0 = 0 +6:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:16/0/physics_layer_0/angular_velocity = 0.0 +7:16/0 = 0 +7:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:16/0/physics_layer_0/angular_velocity = 0.0 +8:16/0 = 0 +8:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:16/0/physics_layer_0/angular_velocity = 0.0 +9:16/0 = 0 +9:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:16/0/physics_layer_0/angular_velocity = 0.0 +10:16/0 = 0 +10:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:16/0/physics_layer_0/angular_velocity = 0.0 +11:16/0 = 0 +11:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:16/0/physics_layer_0/angular_velocity = 0.0 +12:16/0 = 0 +12:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:16/0/physics_layer_0/angular_velocity = 0.0 +13:16/0 = 0 +13:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:16/0/physics_layer_0/angular_velocity = 0.0 +14:16/0 = 0 +14:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:16/0/physics_layer_0/angular_velocity = 0.0 +15:16/0 = 0 +15:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:16/0/physics_layer_0/angular_velocity = 0.0 +16:16/0 = 0 +16:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:16/0/physics_layer_0/angular_velocity = 0.0 +17:16/0 = 0 +17:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:16/0/physics_layer_0/angular_velocity = 0.0 +18:16/0 = 0 +18:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:16/0/physics_layer_0/angular_velocity = 0.0 +19:16/0 = 0 +19:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:16/0/physics_layer_0/angular_velocity = 0.0 +20:16/0 = 0 +20:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:16/0/physics_layer_0/angular_velocity = 0.0 +21:16/0 = 0 +21:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:16/0/physics_layer_0/angular_velocity = 0.0 +22:16/0 = 0 +22:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:16/0/physics_layer_0/angular_velocity = 0.0 +23:16/0 = 0 +23:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:16/0/physics_layer_0/angular_velocity = 0.0 +24:16/0 = 0 +24:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:16/0/physics_layer_0/angular_velocity = 0.0 +25:16/0 = 0 +25:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:16/0/physics_layer_0/angular_velocity = 0.0 +26:16/0 = 0 +26:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:16/0/physics_layer_0/angular_velocity = 0.0 +27:16/0 = 0 +27:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:16/0/physics_layer_0/angular_velocity = 0.0 +28:16/0 = 0 +28:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:16/0/physics_layer_0/angular_velocity = 0.0 +29:16/0 = 0 +29:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:16/0/physics_layer_0/angular_velocity = 0.0 +30:16/0 = 0 +30:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:16/0/physics_layer_0/angular_velocity = 0.0 +31:16/0 = 0 +31:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:16/0/physics_layer_0/angular_velocity = 0.0 +32:16/0 = 0 +32:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:16/0/physics_layer_0/angular_velocity = 0.0 +33:16/0 = 0 +33:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:16/0/physics_layer_0/angular_velocity = 0.0 +34:16/0 = 0 +34:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:16/0/physics_layer_0/angular_velocity = 0.0 +35:16/0 = 0 +35:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:16/0/physics_layer_0/angular_velocity = 0.0 +36:16/0 = 0 +36:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:16/0/physics_layer_0/angular_velocity = 0.0 +37:16/0 = 0 +37:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:16/0/physics_layer_0/angular_velocity = 0.0 +38:16/0 = 0 +38:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:16/0/physics_layer_0/angular_velocity = 0.0 +39:16/0 = 0 +39:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:16/0/physics_layer_0/angular_velocity = 0.0 +40:16/0 = 0 +40:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:16/0/physics_layer_0/angular_velocity = 0.0 +41:16/0 = 0 +41:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:16/0/physics_layer_0/angular_velocity = 0.0 +42:16/0 = 0 +42:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:16/0/physics_layer_0/angular_velocity = 0.0 +43:16/0 = 0 +43:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:16/0/physics_layer_0/angular_velocity = 0.0 +44:16/0 = 0 +44:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:16/0/physics_layer_0/angular_velocity = 0.0 +45:16/0 = 0 +45:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:16/0/physics_layer_0/angular_velocity = 0.0 +46:16/0 = 0 +46:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:16/0/physics_layer_0/angular_velocity = 0.0 +47:16/0 = 0 +47:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:16/0/physics_layer_0/angular_velocity = 0.0 +48:16/0 = 0 +48:16/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:16/0/physics_layer_0/angular_velocity = 0.0 +0:17/0 = 0 +0:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:17/0/physics_layer_0/angular_velocity = 0.0 +1:17/0 = 0 +1:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:17/0/physics_layer_0/angular_velocity = 0.0 +2:17/0 = 0 +2:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:17/0/physics_layer_0/angular_velocity = 0.0 +3:17/0 = 0 +3:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:17/0/physics_layer_0/angular_velocity = 0.0 +4:17/0 = 0 +4:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:17/0/physics_layer_0/angular_velocity = 0.0 +5:17/0 = 0 +5:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:17/0/physics_layer_0/angular_velocity = 0.0 +6:17/0 = 0 +6:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:17/0/physics_layer_0/angular_velocity = 0.0 +7:17/0 = 0 +7:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:17/0/physics_layer_0/angular_velocity = 0.0 +8:17/0 = 0 +8:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:17/0/physics_layer_0/angular_velocity = 0.0 +9:17/0 = 0 +9:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:17/0/physics_layer_0/angular_velocity = 0.0 +10:17/0 = 0 +10:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:17/0/physics_layer_0/angular_velocity = 0.0 +11:17/0 = 0 +11:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:17/0/physics_layer_0/angular_velocity = 0.0 +12:17/0 = 0 +12:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:17/0/physics_layer_0/angular_velocity = 0.0 +13:17/0 = 0 +13:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:17/0/physics_layer_0/angular_velocity = 0.0 +14:17/0 = 0 +14:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:17/0/physics_layer_0/angular_velocity = 0.0 +15:17/0 = 0 +15:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:17/0/physics_layer_0/angular_velocity = 0.0 +16:17/0 = 0 +16:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:17/0/physics_layer_0/angular_velocity = 0.0 +17:17/0 = 0 +17:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:17/0/physics_layer_0/angular_velocity = 0.0 +18:17/0 = 0 +18:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:17/0/physics_layer_0/angular_velocity = 0.0 +19:17/0 = 0 +19:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:17/0/physics_layer_0/angular_velocity = 0.0 +20:17/0 = 0 +20:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:17/0/physics_layer_0/angular_velocity = 0.0 +21:17/0 = 0 +21:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:17/0/physics_layer_0/angular_velocity = 0.0 +22:17/0 = 0 +22:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:17/0/physics_layer_0/angular_velocity = 0.0 +23:17/0 = 0 +23:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:17/0/physics_layer_0/angular_velocity = 0.0 +24:17/0 = 0 +24:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:17/0/physics_layer_0/angular_velocity = 0.0 +25:17/0 = 0 +25:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:17/0/physics_layer_0/angular_velocity = 0.0 +26:17/0 = 0 +26:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:17/0/physics_layer_0/angular_velocity = 0.0 +27:17/0 = 0 +27:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:17/0/physics_layer_0/angular_velocity = 0.0 +28:17/0 = 0 +28:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:17/0/physics_layer_0/angular_velocity = 0.0 +29:17/0 = 0 +29:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:17/0/physics_layer_0/angular_velocity = 0.0 +30:17/0 = 0 +30:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:17/0/physics_layer_0/angular_velocity = 0.0 +31:17/0 = 0 +31:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:17/0/physics_layer_0/angular_velocity = 0.0 +32:17/0 = 0 +32:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:17/0/physics_layer_0/angular_velocity = 0.0 +33:17/0 = 0 +33:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:17/0/physics_layer_0/angular_velocity = 0.0 +34:17/0 = 0 +34:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:17/0/physics_layer_0/angular_velocity = 0.0 +35:17/0 = 0 +35:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:17/0/physics_layer_0/angular_velocity = 0.0 +36:17/0 = 0 +36:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:17/0/physics_layer_0/angular_velocity = 0.0 +37:17/0 = 0 +37:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:17/0/physics_layer_0/angular_velocity = 0.0 +38:17/0 = 0 +38:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:17/0/physics_layer_0/angular_velocity = 0.0 +39:17/0 = 0 +39:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:17/0/physics_layer_0/angular_velocity = 0.0 +40:17/0 = 0 +40:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:17/0/physics_layer_0/angular_velocity = 0.0 +41:17/0 = 0 +41:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:17/0/physics_layer_0/angular_velocity = 0.0 +42:17/0 = 0 +42:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:17/0/physics_layer_0/angular_velocity = 0.0 +43:17/0 = 0 +43:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:17/0/physics_layer_0/angular_velocity = 0.0 +44:17/0 = 0 +44:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:17/0/physics_layer_0/angular_velocity = 0.0 +45:17/0 = 0 +45:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:17/0/physics_layer_0/angular_velocity = 0.0 +46:17/0 = 0 +46:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:17/0/physics_layer_0/angular_velocity = 0.0 +47:17/0 = 0 +47:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:17/0/physics_layer_0/angular_velocity = 0.0 +48:17/0 = 0 +48:17/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:17/0/physics_layer_0/angular_velocity = 0.0 +0:18/0 = 0 +0:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:18/0/physics_layer_0/angular_velocity = 0.0 +1:18/0 = 0 +1:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:18/0/physics_layer_0/angular_velocity = 0.0 +2:18/0 = 0 +2:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:18/0/physics_layer_0/angular_velocity = 0.0 +3:18/0 = 0 +3:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:18/0/physics_layer_0/angular_velocity = 0.0 +4:18/0 = 0 +4:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:18/0/physics_layer_0/angular_velocity = 0.0 +5:18/0 = 0 +5:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:18/0/physics_layer_0/angular_velocity = 0.0 +6:18/0 = 0 +6:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:18/0/physics_layer_0/angular_velocity = 0.0 +7:18/0 = 0 +7:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:18/0/physics_layer_0/angular_velocity = 0.0 +8:18/0 = 0 +8:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:18/0/physics_layer_0/angular_velocity = 0.0 +9:18/0 = 0 +9:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:18/0/physics_layer_0/angular_velocity = 0.0 +10:18/0 = 0 +10:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:18/0/physics_layer_0/angular_velocity = 0.0 +11:18/0 = 0 +11:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:18/0/physics_layer_0/angular_velocity = 0.0 +12:18/0 = 0 +12:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:18/0/physics_layer_0/angular_velocity = 0.0 +13:18/0 = 0 +13:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:18/0/physics_layer_0/angular_velocity = 0.0 +14:18/0 = 0 +14:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:18/0/physics_layer_0/angular_velocity = 0.0 +15:18/0 = 0 +15:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:18/0/physics_layer_0/angular_velocity = 0.0 +16:18/0 = 0 +16:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:18/0/physics_layer_0/angular_velocity = 0.0 +17:18/0 = 0 +17:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:18/0/physics_layer_0/angular_velocity = 0.0 +18:18/0 = 0 +18:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:18/0/physics_layer_0/angular_velocity = 0.0 +19:18/0 = 0 +19:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:18/0/physics_layer_0/angular_velocity = 0.0 +20:18/0 = 0 +20:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:18/0/physics_layer_0/angular_velocity = 0.0 +21:18/0 = 0 +21:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:18/0/physics_layer_0/angular_velocity = 0.0 +22:18/0 = 0 +22:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:18/0/physics_layer_0/angular_velocity = 0.0 +23:18/0 = 0 +23:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:18/0/physics_layer_0/angular_velocity = 0.0 +24:18/0 = 0 +24:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:18/0/physics_layer_0/angular_velocity = 0.0 +25:18/0 = 0 +25:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:18/0/physics_layer_0/angular_velocity = 0.0 +26:18/0 = 0 +26:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:18/0/physics_layer_0/angular_velocity = 0.0 +27:18/0 = 0 +27:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:18/0/physics_layer_0/angular_velocity = 0.0 +28:18/0 = 0 +28:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:18/0/physics_layer_0/angular_velocity = 0.0 +29:18/0 = 0 +29:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:18/0/physics_layer_0/angular_velocity = 0.0 +30:18/0 = 0 +30:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:18/0/physics_layer_0/angular_velocity = 0.0 +31:18/0 = 0 +31:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:18/0/physics_layer_0/angular_velocity = 0.0 +32:18/0 = 0 +32:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:18/0/physics_layer_0/angular_velocity = 0.0 +33:18/0 = 0 +33:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:18/0/physics_layer_0/angular_velocity = 0.0 +34:18/0 = 0 +34:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:18/0/physics_layer_0/angular_velocity = 0.0 +35:18/0 = 0 +35:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:18/0/physics_layer_0/angular_velocity = 0.0 +36:18/0 = 0 +36:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:18/0/physics_layer_0/angular_velocity = 0.0 +37:18/0 = 0 +37:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:18/0/physics_layer_0/angular_velocity = 0.0 +38:18/0 = 0 +38:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:18/0/physics_layer_0/angular_velocity = 0.0 +39:18/0 = 0 +39:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:18/0/physics_layer_0/angular_velocity = 0.0 +40:18/0 = 0 +40:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:18/0/physics_layer_0/angular_velocity = 0.0 +41:18/0 = 0 +41:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:18/0/physics_layer_0/angular_velocity = 0.0 +42:18/0 = 0 +42:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:18/0/physics_layer_0/angular_velocity = 0.0 +43:18/0 = 0 +43:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:18/0/physics_layer_0/angular_velocity = 0.0 +44:18/0 = 0 +44:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:18/0/physics_layer_0/angular_velocity = 0.0 +45:18/0 = 0 +45:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:18/0/physics_layer_0/angular_velocity = 0.0 +46:18/0 = 0 +46:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:18/0/physics_layer_0/angular_velocity = 0.0 +47:18/0 = 0 +47:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:18/0/physics_layer_0/angular_velocity = 0.0 +48:18/0 = 0 +48:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:18/0/physics_layer_0/angular_velocity = 0.0 +0:19/0 = 0 +0:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:19/0/physics_layer_0/angular_velocity = 0.0 +1:19/0 = 0 +1:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:19/0/physics_layer_0/angular_velocity = 0.0 +2:19/0 = 0 +2:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:19/0/physics_layer_0/angular_velocity = 0.0 +3:19/0 = 0 +3:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:19/0/physics_layer_0/angular_velocity = 0.0 +4:19/0 = 0 +4:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:19/0/physics_layer_0/angular_velocity = 0.0 +5:19/0 = 0 +5:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:19/0/physics_layer_0/angular_velocity = 0.0 +6:19/0 = 0 +6:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:19/0/physics_layer_0/angular_velocity = 0.0 +7:19/0 = 0 +7:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:19/0/physics_layer_0/angular_velocity = 0.0 +8:19/0 = 0 +8:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:19/0/physics_layer_0/angular_velocity = 0.0 +9:19/0 = 0 +9:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:19/0/physics_layer_0/angular_velocity = 0.0 +10:19/0 = 0 +10:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:19/0/physics_layer_0/angular_velocity = 0.0 +11:19/0 = 0 +11:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:19/0/physics_layer_0/angular_velocity = 0.0 +12:19/0 = 0 +12:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:19/0/physics_layer_0/angular_velocity = 0.0 +13:19/0 = 0 +13:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:19/0/physics_layer_0/angular_velocity = 0.0 +14:19/0 = 0 +14:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:19/0/physics_layer_0/angular_velocity = 0.0 +15:19/0 = 0 +15:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:19/0/physics_layer_0/angular_velocity = 0.0 +16:19/0 = 0 +16:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:19/0/physics_layer_0/angular_velocity = 0.0 +17:19/0 = 0 +17:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:19/0/physics_layer_0/angular_velocity = 0.0 +18:19/0 = 0 +18:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:19/0/physics_layer_0/angular_velocity = 0.0 +19:19/0 = 0 +19:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:19/0/physics_layer_0/angular_velocity = 0.0 +20:19/0 = 0 +20:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:19/0/physics_layer_0/angular_velocity = 0.0 +21:19/0 = 0 +21:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:19/0/physics_layer_0/angular_velocity = 0.0 +22:19/0 = 0 +22:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:19/0/physics_layer_0/angular_velocity = 0.0 +23:19/0 = 0 +23:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:19/0/physics_layer_0/angular_velocity = 0.0 +24:19/0 = 0 +24:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:19/0/physics_layer_0/angular_velocity = 0.0 +25:19/0 = 0 +25:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:19/0/physics_layer_0/angular_velocity = 0.0 +26:19/0 = 0 +26:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:19/0/physics_layer_0/angular_velocity = 0.0 +27:19/0 = 0 +27:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:19/0/physics_layer_0/angular_velocity = 0.0 +28:19/0 = 0 +28:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:19/0/physics_layer_0/angular_velocity = 0.0 +29:19/0 = 0 +29:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:19/0/physics_layer_0/angular_velocity = 0.0 +30:19/0 = 0 +30:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:19/0/physics_layer_0/angular_velocity = 0.0 +31:19/0 = 0 +31:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:19/0/physics_layer_0/angular_velocity = 0.0 +32:19/0 = 0 +32:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:19/0/physics_layer_0/angular_velocity = 0.0 +33:19/0 = 0 +33:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:19/0/physics_layer_0/angular_velocity = 0.0 +34:19/0 = 0 +34:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:19/0/physics_layer_0/angular_velocity = 0.0 +35:19/0 = 0 +35:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:19/0/physics_layer_0/angular_velocity = 0.0 +36:19/0 = 0 +36:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:19/0/physics_layer_0/angular_velocity = 0.0 +37:19/0 = 0 +37:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:19/0/physics_layer_0/angular_velocity = 0.0 +38:19/0 = 0 +38:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:19/0/physics_layer_0/angular_velocity = 0.0 +39:19/0 = 0 +39:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:19/0/physics_layer_0/angular_velocity = 0.0 +40:19/0 = 0 +40:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:19/0/physics_layer_0/angular_velocity = 0.0 +41:19/0 = 0 +41:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:19/0/physics_layer_0/angular_velocity = 0.0 +42:19/0 = 0 +42:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:19/0/physics_layer_0/angular_velocity = 0.0 +43:19/0 = 0 +43:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:19/0/physics_layer_0/angular_velocity = 0.0 +44:19/0 = 0 +44:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:19/0/physics_layer_0/angular_velocity = 0.0 +45:19/0 = 0 +45:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:19/0/physics_layer_0/angular_velocity = 0.0 +46:19/0 = 0 +46:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:19/0/physics_layer_0/angular_velocity = 0.0 +47:19/0 = 0 +47:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:19/0/physics_layer_0/angular_velocity = 0.0 +48:19/0 = 0 +48:19/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:19/0/physics_layer_0/angular_velocity = 0.0 +0:20/0 = 0 +0:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:20/0/physics_layer_0/angular_velocity = 0.0 +1:20/0 = 0 +1:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:20/0/physics_layer_0/angular_velocity = 0.0 +2:20/0 = 0 +2:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:20/0/physics_layer_0/angular_velocity = 0.0 +3:20/0 = 0 +3:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:20/0/physics_layer_0/angular_velocity = 0.0 +4:20/0 = 0 +4:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:20/0/physics_layer_0/angular_velocity = 0.0 +5:20/0 = 0 +5:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:20/0/physics_layer_0/angular_velocity = 0.0 +6:20/0 = 0 +6:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:20/0/physics_layer_0/angular_velocity = 0.0 +7:20/0 = 0 +7:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:20/0/physics_layer_0/angular_velocity = 0.0 +8:20/0 = 0 +8:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:20/0/physics_layer_0/angular_velocity = 0.0 +9:20/0 = 0 +9:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:20/0/physics_layer_0/angular_velocity = 0.0 +10:20/0 = 0 +10:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:20/0/physics_layer_0/angular_velocity = 0.0 +11:20/0 = 0 +11:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:20/0/physics_layer_0/angular_velocity = 0.0 +12:20/0 = 0 +12:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:20/0/physics_layer_0/angular_velocity = 0.0 +13:20/0 = 0 +13:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:20/0/physics_layer_0/angular_velocity = 0.0 +14:20/0 = 0 +14:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:20/0/physics_layer_0/angular_velocity = 0.0 +15:20/0 = 0 +15:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:20/0/physics_layer_0/angular_velocity = 0.0 +16:20/0 = 0 +16:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:20/0/physics_layer_0/angular_velocity = 0.0 +17:20/0 = 0 +17:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:20/0/physics_layer_0/angular_velocity = 0.0 +18:20/0 = 0 +18:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:20/0/physics_layer_0/angular_velocity = 0.0 +19:20/0 = 0 +19:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:20/0/physics_layer_0/angular_velocity = 0.0 +20:20/0 = 0 +20:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:20/0/physics_layer_0/angular_velocity = 0.0 +21:20/0 = 0 +21:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:20/0/physics_layer_0/angular_velocity = 0.0 +22:20/0 = 0 +22:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:20/0/physics_layer_0/angular_velocity = 0.0 +23:20/0 = 0 +23:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:20/0/physics_layer_0/angular_velocity = 0.0 +24:20/0 = 0 +24:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:20/0/physics_layer_0/angular_velocity = 0.0 +25:20/0 = 0 +25:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:20/0/physics_layer_0/angular_velocity = 0.0 +26:20/0 = 0 +26:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:20/0/physics_layer_0/angular_velocity = 0.0 +27:20/0 = 0 +27:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:20/0/physics_layer_0/angular_velocity = 0.0 +28:20/0 = 0 +28:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:20/0/physics_layer_0/angular_velocity = 0.0 +29:20/0 = 0 +29:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:20/0/physics_layer_0/angular_velocity = 0.0 +30:20/0 = 0 +30:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:20/0/physics_layer_0/angular_velocity = 0.0 +31:20/0 = 0 +31:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:20/0/physics_layer_0/angular_velocity = 0.0 +32:20/0 = 0 +32:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:20/0/physics_layer_0/angular_velocity = 0.0 +33:20/0 = 0 +33:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:20/0/physics_layer_0/angular_velocity = 0.0 +34:20/0 = 0 +34:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:20/0/physics_layer_0/angular_velocity = 0.0 +35:20/0 = 0 +35:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:20/0/physics_layer_0/angular_velocity = 0.0 +36:20/0 = 0 +36:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:20/0/physics_layer_0/angular_velocity = 0.0 +37:20/0 = 0 +37:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:20/0/physics_layer_0/angular_velocity = 0.0 +38:20/0 = 0 +38:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:20/0/physics_layer_0/angular_velocity = 0.0 +39:20/0 = 0 +39:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:20/0/physics_layer_0/angular_velocity = 0.0 +40:20/0 = 0 +40:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:20/0/physics_layer_0/angular_velocity = 0.0 +41:20/0 = 0 +41:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:20/0/physics_layer_0/angular_velocity = 0.0 +42:20/0 = 0 +42:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:20/0/physics_layer_0/angular_velocity = 0.0 +43:20/0 = 0 +43:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:20/0/physics_layer_0/angular_velocity = 0.0 +44:20/0 = 0 +44:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:20/0/physics_layer_0/angular_velocity = 0.0 +45:20/0 = 0 +45:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:20/0/physics_layer_0/angular_velocity = 0.0 +46:20/0 = 0 +46:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:20/0/physics_layer_0/angular_velocity = 0.0 +47:20/0 = 0 +47:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:20/0/physics_layer_0/angular_velocity = 0.0 +48:20/0 = 0 +48:20/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:20/0/physics_layer_0/angular_velocity = 0.0 +0:21/0 = 0 +0:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:21/0/physics_layer_0/angular_velocity = 0.0 +1:21/0 = 0 +1:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +1:21/0/physics_layer_0/angular_velocity = 0.0 +2:21/0 = 0 +2:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +2:21/0/physics_layer_0/angular_velocity = 0.0 +3:21/0 = 0 +3:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +3:21/0/physics_layer_0/angular_velocity = 0.0 +4:21/0 = 0 +4:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +4:21/0/physics_layer_0/angular_velocity = 0.0 +5:21/0 = 0 +5:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +5:21/0/physics_layer_0/angular_velocity = 0.0 +6:21/0 = 0 +6:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +6:21/0/physics_layer_0/angular_velocity = 0.0 +7:21/0 = 0 +7:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +7:21/0/physics_layer_0/angular_velocity = 0.0 +8:21/0 = 0 +8:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +8:21/0/physics_layer_0/angular_velocity = 0.0 +9:21/0 = 0 +9:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +9:21/0/physics_layer_0/angular_velocity = 0.0 +10:21/0 = 0 +10:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +10:21/0/physics_layer_0/angular_velocity = 0.0 +11:21/0 = 0 +11:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +11:21/0/physics_layer_0/angular_velocity = 0.0 +12:21/0 = 0 +12:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +12:21/0/physics_layer_0/angular_velocity = 0.0 +13:21/0 = 0 +13:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +13:21/0/physics_layer_0/angular_velocity = 0.0 +14:21/0 = 0 +14:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +14:21/0/physics_layer_0/angular_velocity = 0.0 +15:21/0 = 0 +15:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +15:21/0/physics_layer_0/angular_velocity = 0.0 +16:21/0 = 0 +16:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +16:21/0/physics_layer_0/angular_velocity = 0.0 +17:21/0 = 0 +17:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +17:21/0/physics_layer_0/angular_velocity = 0.0 +18:21/0 = 0 +18:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:21/0/physics_layer_0/angular_velocity = 0.0 +19:21/0 = 0 +19:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +19:21/0/physics_layer_0/angular_velocity = 0.0 +20:21/0 = 0 +20:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +20:21/0/physics_layer_0/angular_velocity = 0.0 +21:21/0 = 0 +21:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +21:21/0/physics_layer_0/angular_velocity = 0.0 +22:21/0 = 0 +22:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +22:21/0/physics_layer_0/angular_velocity = 0.0 +23:21/0 = 0 +23:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +23:21/0/physics_layer_0/angular_velocity = 0.0 +24:21/0 = 0 +24:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +24:21/0/physics_layer_0/angular_velocity = 0.0 +25:21/0 = 0 +25:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +25:21/0/physics_layer_0/angular_velocity = 0.0 +26:21/0 = 0 +26:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +26:21/0/physics_layer_0/angular_velocity = 0.0 +27:21/0 = 0 +27:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +27:21/0/physics_layer_0/angular_velocity = 0.0 +28:21/0 = 0 +28:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +28:21/0/physics_layer_0/angular_velocity = 0.0 +29:21/0 = 0 +29:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +29:21/0/physics_layer_0/angular_velocity = 0.0 +30:21/0 = 0 +30:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +30:21/0/physics_layer_0/angular_velocity = 0.0 +31:21/0 = 0 +31:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +31:21/0/physics_layer_0/angular_velocity = 0.0 +32:21/0 = 0 +32:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +32:21/0/physics_layer_0/angular_velocity = 0.0 +33:21/0 = 0 +33:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +33:21/0/physics_layer_0/angular_velocity = 0.0 +34:21/0 = 0 +34:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +34:21/0/physics_layer_0/angular_velocity = 0.0 +35:21/0 = 0 +35:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +35:21/0/physics_layer_0/angular_velocity = 0.0 +36:21/0 = 0 +36:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +36:21/0/physics_layer_0/angular_velocity = 0.0 +37:21/0 = 0 +37:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +37:21/0/physics_layer_0/angular_velocity = 0.0 +38:21/0 = 0 +38:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +38:21/0/physics_layer_0/angular_velocity = 0.0 +39:21/0 = 0 +39:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +39:21/0/physics_layer_0/angular_velocity = 0.0 +40:21/0 = 0 +40:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +40:21/0/physics_layer_0/angular_velocity = 0.0 +41:21/0 = 0 +41:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +41:21/0/physics_layer_0/angular_velocity = 0.0 +42:21/0 = 0 +42:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +42:21/0/physics_layer_0/angular_velocity = 0.0 +43:21/0 = 0 +43:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +43:21/0/physics_layer_0/angular_velocity = 0.0 +44:21/0 = 0 +44:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +44:21/0/physics_layer_0/angular_velocity = 0.0 +45:21/0 = 0 +45:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +45:21/0/physics_layer_0/angular_velocity = 0.0 +46:21/0 = 0 +46:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +46:21/0/physics_layer_0/angular_velocity = 0.0 +47:21/0 = 0 +47:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +47:21/0/physics_layer_0/angular_velocity = 0.0 +48:21/0 = 0 +48:21/0/physics_layer_0/linear_velocity = Vector2(0, 0) +48:21/0/physics_layer_0/angular_velocity = 0.0 +18:0/0 = 0 +18:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +18:0/0/physics_layer_0/angular_velocity = 0.0 +18:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) + +[sub_resource type="TileSetScenesCollectionSource" id="TileSetScenesCollectionSource_mi6dp"] +scenes/3/scene = ExtResource("3_uqirg") +scenes/4/scene = ExtResource("2_poklm") + +[resource] +physics_layer_0/collision_layer = 1 +sources/1 = SubResource("TileSetAtlasSource_ari5a") +sources/3 = SubResource("TileSetScenesCollectionSource_mi6dp") diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index dc4fbc6..764c1ea 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -16,7 +16,8 @@ func _ready() -> void: func _on_inspection() -> void: if !opened: - ui.render_text(['I warned you about jayden making ui!!!','now it is in an array','songboots would be nice']) + opened = true + ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) $Sprite2D.frame = 1 diff --git a/src/scene-tiles/stairs/stairs.gd b/src/scene-tiles/stairs/stairs.gd new file mode 100644 index 0000000..c0ff3de --- /dev/null +++ b/src/scene-tiles/stairs/stairs.gd @@ -0,0 +1,8 @@ +extends Area2D + + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + add_to_group('stairs') + pass # Replace with function body. + diff --git a/src/scene-tiles/stairs/stairs.tscn b/src/scene-tiles/stairs/stairs.tscn new file mode 100644 index 0000000..64e00e9 --- /dev/null +++ b/src/scene-tiles/stairs/stairs.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=4 format=3 uid="uid://cmdlpc0uddsm2"] + +[ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_cirol"] +[ext_resource type="Script" path="res://src/scene-tiles/stairs/stairs.gd" id="1_ww3tu"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_8vrfj"] +size = Vector2(16, 16) + +[node name="stairs" type="Area2D"] +script = ExtResource("1_ww3tu") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("RectangleShape2D_8vrfj") + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_cirol") +region_enabled = true +region_rect = Rect2(48, 96, 16, 16) From 69d141e93dd6e3c9deac2447d11dc9ec71d9fe3e Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Thu, 21 Mar 2024 10:55:21 -0400 Subject: [PATCH 40/86] manually added Tigrans contributions --- src/boots/boo1690.tmp | 6 ++++++ src/boots/boots.gd | 46 +++++++++++++++++++++++++++++++++++++++++++ src/boots/boots.tscn | 6 ++++++ src/maps/map.gd | 3 ++- src/player/player.gd | 31 ++++++++++++++++++++++------- 5 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 src/boots/boo1690.tmp create mode 100644 src/boots/boots.gd create mode 100644 src/boots/boots.tscn diff --git a/src/boots/boo1690.tmp b/src/boots/boo1690.tmp new file mode 100644 index 0000000..f9fcf8b --- /dev/null +++ b/src/boots/boo1690.tmp @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://dtgyaic6xsu0h"] + +[ext_resource type="Script" path="res://src/boots/boots.gd" id="1_1p87s"] + +[node name="Boots" type="Node2D"] +script = ExtResource("1_1p87s") diff --git a/src/boots/boots.gd b/src/boots/boots.gd new file mode 100644 index 0000000..18cf409 --- /dev/null +++ b/src/boots/boots.gd @@ -0,0 +1,46 @@ +extends Node2D + + +var winning_move_sequence: Array[String] = ["down","down","down","down","down"] +var past_5_moves: Array[String] = ["","","","",""] + +# Called when the node enters the scene tree for the first time. + +func _ready() -> void: + print("BOOTS ON!!!") + connect_to_player() + +func connect_to_player() -> void: + var parent_player_node = get_node("../") + # Yeah!! You can get stuff 2 parents up the tree get_node("../../") + if parent_player_node != self: + parent_player_node.made_successful_move.connect(new_move_made) + pass + +func new_move_made(dir: Vector2) -> void: + match dir: + Vector2(0,1): + note_new_move("down") + pass + Vector2(0,-1): + note_new_move("up") + pass + Vector2(1,0): + note_new_move("right") + pass + Vector2(-1,0): + note_new_move("left") + pass + has_player_won() + pass + +func note_new_move(what_direction_string: String) -> void: + past_5_moves.pop_front() + past_5_moves.append(what_direction_string) + print(past_5_moves) + pass + +func has_player_won() -> void: + if past_5_moves == winning_move_sequence: + print("yayay!! You won!") + pass diff --git a/src/boots/boots.tscn b/src/boots/boots.tscn new file mode 100644 index 0000000..f9fcf8b --- /dev/null +++ b/src/boots/boots.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://dtgyaic6xsu0h"] + +[ext_resource type="Script" path="res://src/boots/boots.gd" id="1_1p87s"] + +[node name="Boots" type="Node2D"] +script = ExtResource("1_1p87s") diff --git a/src/maps/map.gd b/src/maps/map.gd index fe88449..ad31bcd 100644 --- a/src/maps/map.gd +++ b/src/maps/map.gd @@ -1,9 +1,10 @@ class_name Map extends Node2D - +@onready var tilemap:TileMap = $TileMap # Called when the node enters the scene tree for the first time. func _ready() -> void: + tilemap.add_to_group('wall') pass # Replace with function body. diff --git a/src/player/player.gd b/src/player/player.gd index a6bfd75..ad004fa 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -1,13 +1,17 @@ class_name Player extends Area2D +@onready var boots_packed_scene: PackedScene = preload("res://src/boots/boots.tscn") @onready var raycast := $RayCast2D signal walked_into_stairs +signal made_successful_move(successful_input_dir) const TILE_SIZE := 16 var is_actionable:= true +var has_boots := false + func _init() -> void: add_to_group("player") @@ -48,14 +52,20 @@ func _move(_input_dir:Vector2) -> void: raycast.force_raycast_update() var next_tile: Object = raycast.get_collider() - if next_tile != null: - print(next_tile) - - if next_tile == null: + #if next_tile != null: + #print(next_tile) + # if it's a tile you can interact with you can't walk on it + # maybe we could use class names or something that dosen't require making new labels for everything (not an issue rn) + if next_tile == null or !next_tile.is_in_group('interact'): position += _input_dir * TILE_SIZE - elif next_tile.is_in_group('stairs'): - walked_into_stairs.emit() + made_successful_move.emit(_input_dir) + check_next_tile(next_tile) +func check_next_tile(tile: Object) -> void: + if tile == null: + return + if tile.is_in_group('stairs'): + walked_into_stairs.emit() func _inspect() -> void: raycast.force_raycast_update() @@ -65,7 +75,14 @@ func _inspect() -> void: return if inspect_tile.is_in_group('chest'): inspect_tile._on_inspection() - pass + #very very very bad fix asap + # pass in player into inspection function or something + if !has_boots: + print('boots') + var new_obtained_boots = boots_packed_scene.instantiate() + self.add_child(new_obtained_boots) + has_boots = true + pass pass From 28d373758935ccbf2edc0f85c3182afa15ede445 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 23 Mar 2024 18:12:21 -0400 Subject: [PATCH 41/86] cleaned up codebase a bit --- project.godot | 2 +- src/boots/boots.gd | 33 +++++++++++++---------------- src/main/ui.gd | 5 ++--- src/maps/map.gd | 5 ++--- src/player/player.gd | 36 ++++++++++---------------------- src/resources/map_tileset.tres | 1 + src/scene-tiles/chest/chest.gd | 10 ++++++++- src/scene-tiles/stairs/stairs.gd | 1 + 8 files changed, 41 insertions(+), 52 deletions(-) diff --git a/project.godot b/project.godot index 8c5872d..b834fbd 100644 --- a/project.godot +++ b/project.godot @@ -26,7 +26,7 @@ window/stretch/scale_mode="integer" [input] -inspect={ +interact={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) ] diff --git a/src/boots/boots.gd b/src/boots/boots.gd index 18cf409..2ffbbe8 100644 --- a/src/boots/boots.gd +++ b/src/boots/boots.gd @@ -1,8 +1,8 @@ extends Node2D -var winning_move_sequence: Array[String] = ["down","down","down","down","down"] -var past_5_moves: Array[String] = ["","","","",""] +var move_code: Array[String] = ["down","down","down","down","down"] +var recent_moves: Array[String] = ["","","","",""] # Called when the node enters the scene tree for the first time. @@ -11,36 +11,31 @@ func _ready() -> void: connect_to_player() func connect_to_player() -> void: - var parent_player_node = get_node("../") + var player := get_node("../") # Yeah!! You can get stuff 2 parents up the tree get_node("../../") - if parent_player_node != self: - parent_player_node.made_successful_move.connect(new_move_made) - pass + if player != self: + player.moved.connect(player_moved) -func new_move_made(dir: Vector2) -> void: +func player_moved(dir: Vector2) -> void: match dir: Vector2(0,1): - note_new_move("down") + push_move("down") pass Vector2(0,-1): - note_new_move("up") + push_move("up") pass Vector2(1,0): - note_new_move("right") + push_move("right") pass Vector2(-1,0): - note_new_move("left") + push_move("left") pass has_player_won() - pass -func note_new_move(what_direction_string: String) -> void: - past_5_moves.pop_front() - past_5_moves.append(what_direction_string) - print(past_5_moves) - pass +func push_move(what_direction_string: String) -> void: + recent_moves.pop_front() + recent_moves.append(what_direction_string) func has_player_won() -> void: - if past_5_moves == winning_move_sequence: + if recent_moves == move_code: print("yayay!! You won!") - pass diff --git a/src/main/ui.gd b/src/main/ui.gd index bdde533..a7c02d2 100644 --- a/src/main/ui.gd +++ b/src/main/ui.gd @@ -14,12 +14,11 @@ func render_text(new_text_arr) -> void: bootIcon.visible = true textbox.visible = true var textLabel = $Textbox/Text - #i = 0 - #while i < new_text_arr.length(): + for line in new_text_arr: textLabel.text = line await text_advanced - #await text_advanced + textbox.visible = false text_removed.emit() diff --git a/src/maps/map.gd b/src/maps/map.gd index ad31bcd..d392bb2 100644 --- a/src/maps/map.gd +++ b/src/maps/map.gd @@ -1,13 +1,12 @@ class_name Map extends Node2D +# we need to add a collision shape to the tilemap for the player raycast to be able to detect it, otherwise it'll be considered null. + @onready var tilemap:TileMap = $TileMap -# Called when the node enters the scene tree for the first time. func _ready() -> void: tilemap.add_to_group('wall') - pass # Replace with function body. -# Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass diff --git a/src/player/player.gd b/src/player/player.gd index ad004fa..9a5a421 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -5,7 +5,7 @@ extends Area2D @onready var raycast := $RayCast2D signal walked_into_stairs -signal made_successful_move(successful_input_dir) +signal moved(dir) const TILE_SIZE := 16 var is_actionable:= true @@ -42,8 +42,8 @@ func _input(event: InputEvent) -> void: if _input_dir != Vector2.ZERO: _move(_input_dir) return - if event.is_action_pressed('inspect'): - _inspect() + if event.is_action_pressed('interact'): + _interact() func _move(_input_dir:Vector2) -> void: @@ -52,13 +52,9 @@ func _move(_input_dir:Vector2) -> void: raycast.force_raycast_update() var next_tile: Object = raycast.get_collider() - #if next_tile != null: - #print(next_tile) - # if it's a tile you can interact with you can't walk on it - # maybe we could use class names or something that dosen't require making new labels for everything (not an issue rn) - if next_tile == null or !next_tile.is_in_group('interact'): + if next_tile == null or next_tile.is_in_group('walkable'): position += _input_dir * TILE_SIZE - made_successful_move.emit(_input_dir) + moved.emit(_input_dir) check_next_tile(next_tile) func check_next_tile(tile: Object) -> void: @@ -67,22 +63,12 @@ func check_next_tile(tile: Object) -> void: if tile.is_in_group('stairs'): walked_into_stairs.emit() -func _inspect() -> void: +func _interact() -> void: raycast.force_raycast_update() - var inspect_tile: Object = raycast.get_collider() - if inspect_tile == null: + var interact_tile: Object = raycast.get_collider() + if interact_tile == null: print('wow nothing!') return - if inspect_tile.is_in_group('chest'): - inspect_tile._on_inspection() - #very very very bad fix asap - # pass in player into inspection function or something - if !has_boots: - print('boots') - var new_obtained_boots = boots_packed_scene.instantiate() - self.add_child(new_obtained_boots) - has_boots = true - pass - - - pass + if interact_tile.is_in_group('interact'): + interact_tile._on_interaction(self) + diff --git a/src/resources/map_tileset.tres b/src/resources/map_tileset.tres index e471ef7..6fa79eb 100644 --- a/src/resources/map_tileset.tres +++ b/src/resources/map_tileset.tres @@ -2668,6 +2668,7 @@ texture = ExtResource("1_q6o4g") 4:18/0 = 0 4:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) 4:18/0/physics_layer_0/angular_velocity = 0.0 +4:18/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) 5:18/0 = 0 5:18/0/physics_layer_0/linear_velocity = Vector2(0, 0) 5:18/0/physics_layer_0/angular_velocity = 0.0 diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 764c1ea..1316976 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -14,9 +14,17 @@ func _init() -> void: func _ready() -> void: pass -func _on_inspection() -> void: +func _on_interaction(player:Player) -> void: if !opened: opened = true + + # we should make a generic chest with the ability to give any item (although we'd need to have some sort of item data strucutre) + if !player.has_boots: + print('boots') + var boots = player.boots_packed_scene.instantiate() + player.add_child(boots) + player.has_boots = true + ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) $Sprite2D.frame = 1 diff --git a/src/scene-tiles/stairs/stairs.gd b/src/scene-tiles/stairs/stairs.gd index c0ff3de..b57aeb8 100644 --- a/src/scene-tiles/stairs/stairs.gd +++ b/src/scene-tiles/stairs/stairs.gd @@ -3,6 +3,7 @@ extends Area2D # Called when the node enters the scene tree for the first time. func _ready() -> void: + add_to_group('walkable') add_to_group('stairs') pass # Replace with function body. From 221788d7d38fac2fd2c496ba60c826b8bdd52b41 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 23 Mar 2024 18:22:21 -0400 Subject: [PATCH 42/86] even cleanergit add -A! --- src/boots/boots.gd | 17 ++++++++--------- src/main/main.gd | 2 -- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/boots/boots.gd b/src/boots/boots.gd index 2ffbbe8..fa7a0cc 100644 --- a/src/boots/boots.gd +++ b/src/boots/boots.gd @@ -11,10 +11,8 @@ func _ready() -> void: connect_to_player() func connect_to_player() -> void: - var player := get_node("../") - # Yeah!! You can get stuff 2 parents up the tree get_node("../../") - if player != self: - player.moved.connect(player_moved) + var player := get_parent() + player.moved.connect(player_moved) func player_moved(dir: Vector2) -> void: match dir: @@ -30,12 +28,13 @@ func player_moved(dir: Vector2) -> void: Vector2(-1,0): push_move("left") pass - has_player_won() -func push_move(what_direction_string: String) -> void: + if recent_moves == move_code: + code_entered() + +func push_move(dir_string: String) -> void: recent_moves.pop_front() - recent_moves.append(what_direction_string) + recent_moves.append(dir_string) -func has_player_won() -> void: - if recent_moves == move_code: +func code_entered(): print("yayay!! You won!") diff --git a/src/main/main.gd b/src/main/main.gd index 0fa48e3..c332444 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -36,8 +36,6 @@ func swap_map() -> void: player.position = playerSpawnMarker.position - - func _start_cutscene() -> void: in_cutscene = true player.is_actionable = false From f38e93de95c3778d80ba9f24e85aeb3b58af140e Mon Sep 17 00:00:00 2001 From: Haigsov <haigsouv@my.yorku.ca> Date: Sat, 23 Mar 2024 18:55:02 -0400 Subject: [PATCH 43/86] Changed maps from dictionary to array --- src/main/main.gd | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/main/main.gd b/src/main/main.gd index c332444..03da977 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -6,41 +6,41 @@ extends Node2D var in_cutscene := false -var maps:Dictionary = {0:preload('res://src/maps/map-1.tscn'),1:preload('res://src/maps/map-2.tscn'),2:preload('res://src/maps/map-3.tscn')} +var maps:Array = [preload('res://src/maps/map-1.tscn'),preload('res://src/maps/map-2.tscn'),preload('res://src/maps/map-3.tscn')] var shuffled_maps:Array = [] var current_map_id func _ready() -> void: - ui.text_rendered.connect(_start_cutscene) - ui.text_removed.connect(_end_cutscene) - player.walked_into_stairs.connect(swap_map) - pass + ui.text_rendered.connect(_start_cutscene) + ui.text_removed.connect(_end_cutscene) + player.walked_into_stairs.connect(swap_map) + pass func swap_map() -> void: - #reshuffle rooms if we've visted them all - if shuffled_maps.size() == 0: - shuffled_maps = Array(range(maps.size())) - shuffled_maps.shuffle() - #pick new room from remaining choices - var next_map_id :int = shuffled_maps.pop_front() - var nextMap:Node2D = maps[next_map_id].instantiate() + #reshuffle rooms if we've visted them all + if shuffled_maps.size() == 0: + shuffled_maps = Array(range(maps.size())) + shuffled_maps.shuffle() + #pick new room from remaining choices + var next_map_id :int = shuffled_maps.pop_front() + var nextMap:Node2D = maps[next_map_id].instantiate() - #load new map - current_map.queue_free() - add_child(nextMap) - current_map = nextMap + #load new map + current_map.queue_free() + add_child(nextMap) + current_map = nextMap - #move the player to the spawn point - var playerSpawnMarker:Marker2D = nextMap.get_node('PlayerSpawn') - player.position = playerSpawnMarker.position + #move the player to the spawn point + var playerSpawnMarker:Marker2D = nextMap.get_node('PlayerSpawn') + player.position = playerSpawnMarker.position func _start_cutscene() -> void: - in_cutscene = true - player.is_actionable = false + in_cutscene = true + player.is_actionable = false func _end_cutscene() -> void: - in_cutscene = false - await get_tree().create_timer(0.01).timeout # 10ms buffer hack to prevent input collision from text advancing and player input, could also solve by checking UI input in player _input event? - player.is_actionable = true + in_cutscene = false + await get_tree().create_timer(0.01).timeout # 10ms buffer hack to prevent input collision from text advancing and player input, could also solve by checking UI input in player _input event? + player.is_actionable = true From c7b90cb3f4911e8db98aa2ddf26c1dc238dfe902 Mon Sep 17 00:00:00 2001 From: Haigsov <haigsouv@my.yorku.ca> Date: Sat, 23 Mar 2024 21:20:53 -0400 Subject: [PATCH 44/86] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f89d046..75eb8af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ # Godot 4+ specific ignores .godot/ -.vscode/ \ No newline at end of file +.vscode/settings.json From ca8bb9f7e3b015722530cae30666928c9d7d0e7e Mon Sep 17 00:00:00 2001 From: Haigsov <haigsouv@my.yorku.ca> Date: Sun, 24 Mar 2024 23:34:24 -0400 Subject: [PATCH 45/86] Added new case for opening chest when wearing boots --- src/scene-tiles/chest/chest.gd | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 1316976..643a03b 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -25,7 +25,14 @@ func _on_interaction(player:Player) -> void: player.add_child(boots) player.has_boots = true - ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) - $Sprite2D.frame = 1 + ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) + $Sprite2D.frame = 1 + + # added a cheeky placeholder if statement for when the player is already wearing boots and opens a new chest + # did it for shits and giggles + elif player.has_boots: + print('boots again?') + + ui.render_text(['The chest contained the same boots.', "The ones you're already wearing.", 'You don\'t need them right now.']) From 13babcddcf13e8bcd59082e3f9fa868b6499f4b5 Mon Sep 17 00:00:00 2001 From: Haigsov <haigsouv@my.yorku.ca> Date: Sat, 30 Mar 2024 23:36:14 -0400 Subject: [PATCH 46/86] Create The Maze.md --- The Maze.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 The Maze.md diff --git a/The Maze.md b/The Maze.md new file mode 100644 index 0000000..284f149 --- /dev/null +++ b/The Maze.md @@ -0,0 +1,52 @@ +# Main Gameplay loop +Puzzle RPG +interacting with NPCs and using their info to solve puzzles while also fighting enemies using grid movement turn based combat (similar to crypt of the necrodancer) and might have magic spells, might. +# Verbs (mechanics) +Movement before boots +Interacting (z) +Movement after boots: 8 different types of sound 4 of them +move one time the other move a second time +## in the talks +melee combat +### can be scrapped +spells +take off boots +# To Do +## Game +What type of sounds do we want? 8 notes on a scale from a particular sound can be an instrument +How de we translate to the player what the sounds do? Chests tell you? should be done in first room? +How many rooms in total? 6 rooms excluding tutorial room +## Enemies +Cows (Chests hate them cause they moo and smell) +Bees (Chests are scared of them cause they sting) +Chests won't talk to you unless you defeat them +## Rooms +Every room has a chest no matter what +### Tutorial Room +How the song boots work? +### Room 1 +1 cow? +### Room 2 +1 bee? +### Room 3 +1 cow 1 bee? +### Room 4 +1 cow 2 bees? +### Room 5 +lying chests? +### Room 6 (extra room) +you fell for the lying chest +your reward: 2 cows 3 bees +### Spells +stun: stuns enemies +buff: gives you more movement +talk to chest: you talk to chest +## Lore +### All chests have song boots +They see you already have them on so they talk to you +### Why are the chests talking? +Because the developer played souls dark and there was a message with "friend ahead" prompt in front of a mimic and thought that she wanted to be friends with the mimics +### The boots overheat you gonna take em off + +### Why song boots? +The golden piece will give you a way but an unconventional way From 78785696d2708dd8d96d9a44f0a666a930955062 Mon Sep 17 00:00:00 2001 From: Haigsov <haigsouv@my.yorku.ca> Date: Sun, 7 Apr 2024 21:22:34 -0400 Subject: [PATCH 47/86] Updated Maze.md --- The Maze.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/The Maze.md b/The Maze.md index 284f149..ceecaf5 100644 --- a/The Maze.md +++ b/The Maze.md @@ -1,7 +1,21 @@ -# Main Gameplay loop +# To do +Levels (easy to make) +## puzzle ideas +Every code is unique +combo puzzle (3 or 4 inputs) +missing rooms (you go from 22 to 24 and you're like oh where 23?) +backtracking to solve in another room +giving items to NPCs (you unlock shit from other rooms and give it to other NPCs) +rooms in jumbled order (1 -> 7 -> 12 -> 3) +#### binary type code +1. Binary code history hud +2. Are we expecting the player to know this or do we teach them +3. How do we communicate this to the player +# Ignore everything below +## Main Gameplay loop Puzzle RPG interacting with NPCs and using their info to solve puzzles while also fighting enemies using grid movement turn based combat (similar to crypt of the necrodancer) and might have magic spells, might. -# Verbs (mechanics) +## Verbs (mechanics) Movement before boots Interacting (z) Movement after boots: 8 different types of sound 4 of them @@ -11,7 +25,7 @@ melee combat ### can be scrapped spells take off boots -# To Do +## To Do ## Game What type of sounds do we want? 8 notes on a scale from a particular sound can be an instrument How de we translate to the player what the sounds do? Chests tell you? should be done in first room? From ba07e40a30a7fdc07bad6a941727ae98388095c0 Mon Sep 17 00:00:00 2001 From: Tigran <122690491+TigranExe@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:54:15 -0400 Subject: [PATCH 48/86] Rework to add room specific stairs -New function to go to next map -New dictionary with assigned maps -Stairs now seperate scene from tilemap that can be assigned a map to go to For future: -Leftover cool code I felt wrong to delete -Just keep the heads up for others to add their level to Main's map_room_id_dict --- docs/contributing.md | 2 +- src/main/main.gd | 20 +++++++++++++++++++- src/maps/map-1.tscn | 9 +++++++-- src/maps/map-2.tscn | 12 ++++++++++-- src/maps/map-3.tscn | 12 ++++++++++-- src/maps/map.gd | 1 + src/player/player.gd | 4 ++-- src/scene-tiles/stairs/stairs.gd | 1 + src/scene-tiles/stairs/stairs.tscn | 2 ++ 9 files changed, 53 insertions(+), 10 deletions(-) diff --git a/docs/contributing.md b/docs/contributing.md index fff40d6..65728f8 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -17,4 +17,4 @@ - Each Scene should do one thing, each function should do one thing - Make [static classes](https://godottutorials.com/courses/introduction-to-gdscript/godot-tutorials-gdscript-20/) when able. - If a custom class/node doesn't have a position on screen or is instanced then removed, then pass it into the script as a object instead of putting in in the scene tree. -- ^ reach out to jayden if you need elaboration on this one \ No newline at end of file +- ^ reach out to jayden if you need elaboration on this one diff --git a/src/main/main.gd b/src/main/main.gd index 03da977..eabe0e6 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -7,6 +7,11 @@ extends Node2D var in_cutscene := false var maps:Array = [preload('res://src/maps/map-1.tscn'),preload('res://src/maps/map-2.tscn'),preload('res://src/maps/map-3.tscn')] +var map_room_id_dict: Dictionary = { #Not perfect but works for time constraint + 1 : preload('res://src/maps/map-1.tscn'), + 2: preload('res://src/maps/map-2.tscn'), + 3: preload('res://src/maps/map-3.tscn') +} var shuffled_maps:Array = [] var current_map_id @@ -14,7 +19,20 @@ var current_map_id func _ready() -> void: ui.text_rendered.connect(_start_cutscene) ui.text_removed.connect(_end_cutscene) - player.walked_into_stairs.connect(swap_map) + player.walked_into_stairs.connect(next_map) + pass + +func next_map(given_room_id: int) -> void: + var next_map_id :int = given_room_id + var nextMap:Node2D = map_room_id_dict[next_map_id].instantiate() + #load new map + current_map.queue_free() + add_child(nextMap) + current_map = nextMap + + #move the player to the spawn point + var playerSpawnMarker:Marker2D = nextMap.get_node('PlayerSpawn') + player.position = playerSpawnMarker.position pass func swap_map() -> void: diff --git a/src/maps/map-1.tscn b/src/maps/map-1.tscn index 5699bf0..52d3adf 100644 --- a/src/maps/map-1.tscn +++ b/src/maps/map-1.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=3 format=3 uid="uid://deqm4to4ptnq0"] +[gd_scene load_steps=4 format=3 uid="uid://deqm4to4ptnq0"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_vosps"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_web8r"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_8x2ye"] [node name="Map" type="Node2D"] script = ExtResource("1_web8r") @@ -10,8 +11,12 @@ script = ExtResource("1_web8r") tile_set = ExtResource("1_vosps") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 196615, 3, 262144, 393226, 3, 196608) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 196615, 3, 262144) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 48) + +[node name="stairs" parent="." instance=ExtResource("3_8x2ye")] +position = Vector2(160, 96) +toward_room_id = 2 diff --git a/src/maps/map-2.tscn b/src/maps/map-2.tscn index edb017b..96ad0c4 100644 --- a/src/maps/map-2.tscn +++ b/src/maps/map-2.tscn @@ -1,15 +1,23 @@ -[gd_scene load_steps=2 format=3 uid="uid://cwxdotd7hh5tb"] +[gd_scene load_steps=4 format=3 uid="uid://cwxdotd7hh5tb"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_2mk3g"] +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_wfc8d"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_wvxh7"] [node name="Map" type="Node2D"] +script = ExtResource("1_wfc8d") +room_id = 2 [node name="TileMap" type="TileMap" parent="."] tile_set = ExtResource("1_2mk3g") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 393219, 3, 196608, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) + +[node name="stairs" parent="." instance=ExtResource("3_wvxh7")] +position = Vector2(160, 96) +toward_room_id = 3 diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn index 192567e..8ca8799 100644 --- a/src/maps/map-3.tscn +++ b/src/maps/map-3.tscn @@ -1,15 +1,23 @@ -[gd_scene load_steps=2 format=3 uid="uid://bapnj7ekqfb0t"] +[gd_scene load_steps=4 format=3 uid="uid://bapnj7ekqfb0t"] +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_kwl2f"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_xfyi1"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_vucpd"] [node name="Map" type="Node2D"] +script = ExtResource("1_kwl2f") +room_id = 3 [node name="TileMap" type="TileMap" parent="."] tile_set = ExtResource("1_xfyi1") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458762, 262145, 18, 458761, 262145, 18, 65550, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 262157, 262145, 18, 196621, 262145, 18, 196620, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 327688, 262145, 18, 393224, 262145, 18, 393223, 262145, 18, 327687, 262145, 18, 327686, 262145, 18, 262150, 262145, 18, 196614, 262145, 18, 196613, 262145, 18, 196612, 262145, 18, 262148, 262145, 18, 262147, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 327685, 262145, 18, 393225, 262145, 18, 393226, 262145, 18, 393227, 262145, 18, 393228, 262145, 18, 393229, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 327693, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 196615, 262145, 18, 262151, 262145, 18, 131082, 3, 262144, 327692, 3, 196608) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458762, 262145, 18, 458761, 262145, 18, 65550, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 262157, 262145, 18, 196621, 262145, 18, 196620, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 327688, 262145, 18, 393224, 262145, 18, 393223, 262145, 18, 327687, 262145, 18, 327686, 262145, 18, 262150, 262145, 18, 196614, 262145, 18, 196613, 262145, 18, 196612, 262145, 18, 262148, 262145, 18, 262147, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 327685, 262145, 18, 393225, 262145, 18, 393226, 262145, 18, 393227, 262145, 18, 393229, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 327693, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 196615, 262145, 18, 262151, 262145, 18, 131082, 3, 262144, 524300, 1245185, 2, 393228, 262145, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(144, 48) + +[node name="stairs" parent="." instance=ExtResource("3_vucpd")] +position = Vector2(192, 80) +toward_room_id = 1 diff --git a/src/maps/map.gd b/src/maps/map.gd index d392bb2..52bbc82 100644 --- a/src/maps/map.gd +++ b/src/maps/map.gd @@ -3,6 +3,7 @@ extends Node2D # we need to add a collision shape to the tilemap for the player raycast to be able to detect it, otherwise it'll be considered null. + @onready var tilemap:TileMap = $TileMap func _ready() -> void: tilemap.add_to_group('wall') diff --git a/src/player/player.gd b/src/player/player.gd index 9a5a421..6929468 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -4,7 +4,7 @@ extends Area2D @onready var boots_packed_scene: PackedScene = preload("res://src/boots/boots.tscn") @onready var raycast := $RayCast2D -signal walked_into_stairs +signal walked_into_stairs(toward_which_room_id) signal moved(dir) const TILE_SIZE := 16 @@ -61,7 +61,7 @@ func check_next_tile(tile: Object) -> void: if tile == null: return if tile.is_in_group('stairs'): - walked_into_stairs.emit() + walked_into_stairs.emit(tile.toward_room_id) func _interact() -> void: raycast.force_raycast_update() diff --git a/src/scene-tiles/stairs/stairs.gd b/src/scene-tiles/stairs/stairs.gd index b57aeb8..4ea5add 100644 --- a/src/scene-tiles/stairs/stairs.gd +++ b/src/scene-tiles/stairs/stairs.gd @@ -1,5 +1,6 @@ extends Area2D +@export var toward_room_id: int = 0 # Called when the node enters the scene tree for the first time. func _ready() -> void: diff --git a/src/scene-tiles/stairs/stairs.tscn b/src/scene-tiles/stairs/stairs.tscn index 64e00e9..e8a68c7 100644 --- a/src/scene-tiles/stairs/stairs.tscn +++ b/src/scene-tiles/stairs/stairs.tscn @@ -10,9 +10,11 @@ size = Vector2(16, 16) script = ExtResource("1_ww3tu") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(8, 8) shape = SubResource("RectangleShape2D_8vrfj") [node name="Sprite2D" type="Sprite2D" parent="."] texture = ExtResource("1_cirol") +offset = Vector2(8, 8) region_enabled = true region_rect = Rect2(48, 96, 16, 16) From fb9745e605693e8872eef951158bab7a936880f7 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Wed, 10 Apr 2024 21:41:06 -0400 Subject: [PATCH 49/86] dialog manager implemented --- addons/dialogue_manager/DialogueManager.cs | 394 ++++ addons/dialogue_manager/LICENSE | 21 + addons/dialogue_manager/assets/icon.svg | 52 + .../dialogue_manager/assets/icon.svg.import | 38 + .../assets/responses_menu.svg | 52 + .../assets/responses_menu.svg.import | 38 + addons/dialogue_manager/assets/update.svg | 71 + .../dialogue_manager/assets/update.svg.import | 37 + .../dialogue_manager/components/code_edit.gd | 425 ++++ .../components/code_edit.tscn | 56 + .../code_edit_syntax_highlighter.gd | 382 ++++ .../components/dialogue_cache.gd | 160 ++ .../components/download_update_panel.gd | 84 + .../components/download_update_panel.tscn | 60 + .../components/errors_panel.gd | 85 + .../components/errors_panel.tscn | 56 + .../dialogue_manager/components/files_list.gd | 144 ++ .../components/files_list.tscn | 40 + .../components/find_in_files.gd | 229 +++ .../components/find_in_files.tscn | 139 ++ .../components/parse_result.gd | 10 + addons/dialogue_manager/components/parser.gd | 1780 +++++++++++++++++ .../components/resolved_line_data.gd | 15 + .../components/resolved_tag_data.gd | 10 + .../components/search_and_replace.gd | 210 ++ .../components/search_and_replace.tscn | 87 + .../dialogue_manager/components/title_list.gd | 67 + .../components/title_list.tscn | 45 + .../components/update_button.gd | 126 ++ .../components/update_button.tscn | 42 + addons/dialogue_manager/constants.gd | 187 ++ addons/dialogue_manager/dialogue_label.gd | 226 +++ addons/dialogue_manager/dialogue_label.tscn | 19 + addons/dialogue_manager/dialogue_line.gd | 98 + addons/dialogue_manager/dialogue_manager.gd | 1235 ++++++++++++ .../dialogue_reponses_menu.gd | 131 ++ addons/dialogue_manager/dialogue_resource.gd | 42 + addons/dialogue_manager/dialogue_response.gd | 62 + .../editor_translation_parser_plugin.gd | 43 + .../example_balloon/ExampleBalloon.cs | 204 ++ .../example_balloon/example_balloon.gd | 141 ++ .../example_balloon/example_balloon.tscn | 149 ++ .../small_example_balloon.tscn | 173 ++ addons/dialogue_manager/import_plugin.gd | 113 ++ addons/dialogue_manager/l10n/en.mo | Bin 0 -> 9770 bytes addons/dialogue_manager/l10n/en.po | 481 +++++ addons/dialogue_manager/l10n/es.po | 457 +++++ addons/dialogue_manager/l10n/translations.pot | 471 +++++ addons/dialogue_manager/l10n/zh.po | 408 ++++ addons/dialogue_manager/l10n/zh_TW.po | 408 ++++ addons/dialogue_manager/plugin.cfg | 7 + addons/dialogue_manager/plugin.gd | 276 +++ addons/dialogue_manager/settings.gd | 184 ++ addons/dialogue_manager/test_scene.gd | 31 + addons/dialogue_manager/test_scene.tscn | 7 + addons/dialogue_manager/utilities/builtins.gd | 468 +++++ addons/dialogue_manager/views/main_view.gd | 1100 ++++++++++ addons/dialogue_manager/views/main_view.tscn | 334 ++++ .../dialogue_manager/views/settings_view.gd | 280 +++ .../dialogue_manager/views/settings_view.tscn | 221 ++ project.godot | 31 + src/autoloads/player_state.gd | 21 + src/dialogue/main.dialogue | 11 + src/dialogue/main.dialogue.import | 15 + src/main/main.gd | 1 + src/maps/map-1.tscn | 10 +- src/maps/map-4.tscn | 17 + src/player/player.gd | 11 +- src/scene-tiles/chest/chest.gd | 50 +- src/scene-tiles/chest/chest.tscn | 2 + 70 files changed, 13053 insertions(+), 27 deletions(-) create mode 100644 addons/dialogue_manager/DialogueManager.cs create mode 100644 addons/dialogue_manager/LICENSE create mode 100644 addons/dialogue_manager/assets/icon.svg create mode 100644 addons/dialogue_manager/assets/icon.svg.import create mode 100644 addons/dialogue_manager/assets/responses_menu.svg create mode 100644 addons/dialogue_manager/assets/responses_menu.svg.import create mode 100644 addons/dialogue_manager/assets/update.svg create mode 100644 addons/dialogue_manager/assets/update.svg.import create mode 100644 addons/dialogue_manager/components/code_edit.gd create mode 100644 addons/dialogue_manager/components/code_edit.tscn create mode 100644 addons/dialogue_manager/components/code_edit_syntax_highlighter.gd create mode 100644 addons/dialogue_manager/components/dialogue_cache.gd create mode 100644 addons/dialogue_manager/components/download_update_panel.gd create mode 100644 addons/dialogue_manager/components/download_update_panel.tscn create mode 100644 addons/dialogue_manager/components/errors_panel.gd create mode 100644 addons/dialogue_manager/components/errors_panel.tscn create mode 100644 addons/dialogue_manager/components/files_list.gd create mode 100644 addons/dialogue_manager/components/files_list.tscn create mode 100644 addons/dialogue_manager/components/find_in_files.gd create mode 100644 addons/dialogue_manager/components/find_in_files.tscn create mode 100644 addons/dialogue_manager/components/parse_result.gd create mode 100644 addons/dialogue_manager/components/parser.gd create mode 100644 addons/dialogue_manager/components/resolved_line_data.gd create mode 100644 addons/dialogue_manager/components/resolved_tag_data.gd create mode 100644 addons/dialogue_manager/components/search_and_replace.gd create mode 100644 addons/dialogue_manager/components/search_and_replace.tscn create mode 100644 addons/dialogue_manager/components/title_list.gd create mode 100644 addons/dialogue_manager/components/title_list.tscn create mode 100644 addons/dialogue_manager/components/update_button.gd create mode 100644 addons/dialogue_manager/components/update_button.tscn create mode 100644 addons/dialogue_manager/constants.gd create mode 100644 addons/dialogue_manager/dialogue_label.gd create mode 100644 addons/dialogue_manager/dialogue_label.tscn create mode 100644 addons/dialogue_manager/dialogue_line.gd create mode 100644 addons/dialogue_manager/dialogue_manager.gd create mode 100644 addons/dialogue_manager/dialogue_reponses_menu.gd create mode 100644 addons/dialogue_manager/dialogue_resource.gd create mode 100644 addons/dialogue_manager/dialogue_response.gd create mode 100644 addons/dialogue_manager/editor_translation_parser_plugin.gd create mode 100644 addons/dialogue_manager/example_balloon/ExampleBalloon.cs create mode 100644 addons/dialogue_manager/example_balloon/example_balloon.gd create mode 100644 addons/dialogue_manager/example_balloon/example_balloon.tscn create mode 100644 addons/dialogue_manager/example_balloon/small_example_balloon.tscn create mode 100644 addons/dialogue_manager/import_plugin.gd create mode 100644 addons/dialogue_manager/l10n/en.mo create mode 100644 addons/dialogue_manager/l10n/en.po create mode 100644 addons/dialogue_manager/l10n/es.po create mode 100644 addons/dialogue_manager/l10n/translations.pot create mode 100644 addons/dialogue_manager/l10n/zh.po create mode 100644 addons/dialogue_manager/l10n/zh_TW.po create mode 100644 addons/dialogue_manager/plugin.cfg create mode 100644 addons/dialogue_manager/plugin.gd create mode 100644 addons/dialogue_manager/settings.gd create mode 100644 addons/dialogue_manager/test_scene.gd create mode 100644 addons/dialogue_manager/test_scene.tscn create mode 100644 addons/dialogue_manager/utilities/builtins.gd create mode 100644 addons/dialogue_manager/views/main_view.gd create mode 100644 addons/dialogue_manager/views/main_view.tscn create mode 100644 addons/dialogue_manager/views/settings_view.gd create mode 100644 addons/dialogue_manager/views/settings_view.tscn create mode 100644 src/autoloads/player_state.gd create mode 100644 src/dialogue/main.dialogue create mode 100644 src/dialogue/main.dialogue.import create mode 100644 src/maps/map-4.tscn diff --git a/addons/dialogue_manager/DialogueManager.cs b/addons/dialogue_manager/DialogueManager.cs new file mode 100644 index 0000000..ae4f931 --- /dev/null +++ b/addons/dialogue_manager/DialogueManager.cs @@ -0,0 +1,394 @@ +using Godot; +using Godot.Collections; +using System; +using System.Reflection; +using System.Threading.Tasks; + +#nullable enable + +namespace DialogueManagerRuntime +{ + public enum TranslationSource + { + None, + Guess, + CSV, + PO + } + + public partial class DialogueManager : Node + { + public delegate void PassedTitleEventHandler(string title); + public delegate void GotDialogueEventHandler(DialogueLine dialogueLine); + public delegate void MutatedEventHandler(Dictionary mutation); + public delegate void DialogueEndedEventHandler(Resource dialogueResource); + + public static PassedTitleEventHandler? PassedTitle; + public static GotDialogueEventHandler? GotDialogue; + public static MutatedEventHandler? Mutated; + public static DialogueEndedEventHandler? DialogueEnded; + + [Signal] public delegate void ResolvedEventHandler(Variant value); + + private static GodotObject? instance; + public static GodotObject Instance + { + get + { + if (instance == null) + { + instance = Engine.GetSingleton("DialogueManager"); + } + return instance; + } + } + + + public static Godot.Collections.Array GameStates + { + get => (Godot.Collections.Array)Instance.Get("game_states"); + set => Instance.Set("game_states", value); + } + + + public static bool IncludeSingletons + { + get => (bool)Instance.Get("include_singletons"); + set => Instance.Set("include_singletons", value); + } + + + public static bool IncludeClasses + { + get => (bool)Instance.Get("include_classes"); + set => Instance.Set("include_classes", value); + } + + + public static TranslationSource TranslationSource + { + get => (TranslationSource)(int)Instance.Get("translation_source"); + set => Instance.Set("translation_source", (int)value); + } + + + public static Func<Node> GetCurrentScene + { + set => Instance.Set("get_current_scene", Callable.From(value)); + } + + + public void Prepare() + { + Instance.Connect("passed_title", Callable.From((string title) => PassedTitle?.Invoke(title))); + Instance.Connect("got_dialogue", Callable.From((RefCounted line) => GotDialogue?.Invoke(new DialogueLine(line)))); + Instance.Connect("mutated", Callable.From((Dictionary mutation) => Mutated?.Invoke(mutation))); + Instance.Connect("dialogue_ended", Callable.From((Resource dialogueResource) => DialogueEnded?.Invoke(dialogueResource))); + } + + + public static async Task<GodotObject> GetSingleton() + { + if (instance != null) return instance; + + var tree = Engine.GetMainLoop(); + int x = 0; + + // Try and find the singleton for a few seconds + while (!Engine.HasSingleton("DialogueManager") && x < 300) + { + await tree.ToSignal(tree, SceneTree.SignalName.ProcessFrame); + x++; + } + + // If it times out something is wrong + if (x >= 300) + { + throw new Exception("The DialogueManager singleton is missing."); + } + + instance = Engine.GetSingleton("DialogueManager"); + return instance; + } + + public static async Task<DialogueLine?> GetNextDialogueLine(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) + { + Instance.Call("_bridge_get_next_dialogue_line", dialogueResource, key, extraGameStates ?? new Array<Variant>()); + var result = await Instance.ToSignal(Instance, "bridge_get_next_dialogue_line_completed"); + + if ((RefCounted)result[0] == null) return null; + + return new DialogueLine((RefCounted)result[0]); + } + + + public static CanvasLayer ShowExampleDialogueBalloon(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) + { + return (CanvasLayer)Instance.Call("show_example_dialogue_balloon", dialogueResource, key, extraGameStates ?? new Array<Variant>()); + } + + + public static Node ShowDialogueBalloonScene(string balloonScene, Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) + { + return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array<Variant>()); + } + + public static Node ShowDialogueBalloonScene(PackedScene balloonScene, Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) + { + return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array<Variant>()); + } + + public static Node ShowDialogueBalloonScene(Node balloonScene, Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) + { + return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array<Variant>()); + } + + + public static Node ShowDialogueBalloon(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) + { + return (Node)Instance.Call("show_dialogue_balloon", dialogueResource, key, extraGameStates ?? new Array<Variant>()); + } + + + public static async void Mutate(Dictionary mutation, Array<Variant>? extraGameStates = null, bool isInlineMutation = false) + { + Instance.Call("_bridge_mutate", mutation, extraGameStates ?? new Array<Variant>(), isInlineMutation); + await Instance.ToSignal(Instance, "bridge_mutated"); + } + + + public bool ThingHasMethod(GodotObject thing, string method) + { + MethodInfo? info = thing.GetType().GetMethod(method, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); + return info != null; + } + + + public async void ResolveThingMethod(GodotObject thing, string method, Array<Variant> args) + { + MethodInfo? info = thing.GetType().GetMethod(method, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); + + if (info == null) return; + +#nullable disable + // Convert the method args to something reflection can handle + ParameterInfo[] argTypes = info.GetParameters(); + object[] _args = new object[argTypes.Length]; + for (int i = 0; i < argTypes.Length; i++) + { + if (i < args.Count && args[i].Obj != null) + { + _args[i] = Convert.ChangeType(args[i].Obj, argTypes[i].ParameterType); + } + else if (argTypes[i].DefaultValue != null) + { + _args[i] = argTypes[i].DefaultValue; + } + } + + // Add a single frame wait in case the method returns before signals can listen + await ToSignal(Engine.GetMainLoop(), SceneTree.SignalName.ProcessFrame); + + if (info.ReturnType == typeof(Task)) + { + await (Task)info.Invoke(thing, _args); + EmitSignal(SignalName.Resolved, null); + } + else + { + var value = (Variant)info.Invoke(thing, _args); + EmitSignal(SignalName.Resolved, value); + } + } +#nullable enable + } + + + public partial class DialogueLine : RefCounted + { + private string type = "dialogue"; + public string Type + { + get => type; + set => type = value; + } + + private string next_id = ""; + public string NextId + { + get => next_id; + set => next_id = value; + } + + private string character = ""; + public string Character + { + get => character; + set => character = value; + } + + private string text = ""; + public string Text + { + get => text; + set => text = value; + } + + private string translation_key = ""; + public string TranslationKey + { + get => translation_key; + set => translation_key = value; + } + + private Array<DialogueResponse> responses = new Array<DialogueResponse>(); + public Array<DialogueResponse> Responses + { + get => responses; + } + + private string? time = null; + public string? Time + { + get => time; + } + + private Dictionary pauses = new Dictionary(); + public Dictionary Pauses + { + get => pauses; + } + + private Dictionary speeds = new Dictionary(); + public Dictionary Speeds + { + get => speeds; + } + + private Array<Godot.Collections.Array> inline_mutations = new Array<Godot.Collections.Array>(); + public Array<Godot.Collections.Array> InlineMutations + { + get => inline_mutations; + } + + private Array<Variant> extra_game_states = new Array<Variant>(); + + private Array<string> tags = new Array<string>(); + public Array<string> Tags + { + get => tags; + } + + public DialogueLine(RefCounted data) + { + type = (string)data.Get("type"); + next_id = (string)data.Get("next_id"); + character = (string)data.Get("character"); + text = (string)data.Get("text"); + translation_key = (string)data.Get("translation_key"); + pauses = (Dictionary)data.Get("pauses"); + speeds = (Dictionary)data.Get("speeds"); + inline_mutations = (Array<Godot.Collections.Array>)data.Get("inline_mutations"); + time = (string)data.Get("time"); + tags = (Array<string>)data.Get("tags"); + + foreach (var response in (Array<RefCounted>)data.Get("responses")) + { + responses.Add(new DialogueResponse(response)); + } + } + + + public string GetTagValue(string tagName) + { + string wrapped = $"{tagName}="; + foreach (var tag in tags) + { + if (tag.StartsWith(wrapped)) + { + return tag.Substring(wrapped.Length); + } + } + return ""; + } + + public override string ToString() + { + switch (type) + { + case "dialogue": + return $"<DialogueLine character=\"{character}\" text=\"{text}\">"; + case "mutation": + return "<DialogueLine mutation>"; + default: + return ""; + } + } + } + + + public partial class DialogueResponse : RefCounted + { + private string next_id = ""; + public string NextId + { + get => next_id; + set => next_id = value; + } + + private bool is_allowed = true; + public bool IsAllowed + { + get => is_allowed; + set => is_allowed = value; + } + + private string text = ""; + public string Text + { + get => text; + set => text = value; + } + + private string translation_key = ""; + public string TranslationKey + { + get => translation_key; + set => translation_key = value; + } + + private Array<string> tags = new Array<string>(); + public Array<string> Tags + { + get => tags; + } + + public DialogueResponse(RefCounted data) + { + next_id = (string)data.Get("next_id"); + is_allowed = (bool)data.Get("is_allowed"); + text = (string)data.Get("text"); + translation_key = (string)data.Get("translation_key"); + tags = (Array<string>)data.Get("tags"); + } + + public string GetTagValue(string tagName) + { + string wrapped = $"{tagName}="; + foreach (var tag in tags) + { + if (tag.StartsWith(wrapped)) + { + return tag.Substring(wrapped.Length); + } + } + return ""; + } + + public override string ToString() + { + return $"<DialogueResponse text=\"{text}\""; + } + } +} + diff --git a/addons/dialogue_manager/LICENSE b/addons/dialogue_manager/LICENSE new file mode 100644 index 0000000..4167139 --- /dev/null +++ b/addons/dialogue_manager/LICENSE @@ -0,0 +1,21 @@ +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. diff --git a/addons/dialogue_manager/assets/icon.svg b/addons/dialogue_manager/assets/icon.svg new file mode 100644 index 0000000..e3b2d4f --- /dev/null +++ b/addons/dialogue_manager/assets/icon.svg @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="16" + height="16" + viewBox="0 0 4.2333333 4.2333335" + version="1.1" + id="svg291" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + sodipodi:docname="icon.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview293" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="px" + showgrid="false" + width="1920px" + units="px" + borderlayer="true" + inkscape:showpageshadow="false" + inkscape:zoom="18.583334" + inkscape:cx="9.3901342" + inkscape:cy="13.506726" + inkscape:window-width="1440" + inkscape:window-height="890" + inkscape:window-x="-6" + inkscape:window-y="-6" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:deskcolor="#d1d1d1" /> + <defs + id="defs288" /> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + id="path3615" + style="clip-rule:evenodd;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.00206088;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:40" + d="M 2.3616237,0.32495581 C 2.2890187,0.32469635 2.2284054,0.32546079 2.1926162,0.32687081 1.8949218,0.33860011 1.5033325,0.34148331 1.2561323,0.35080961 1.1421362,0.35510961 0.51253678,0.28342811 0.31150932,0.54279835 0.0999174,0.81580911 0.23804642,2.0559707 0.22102032,2.2314376 0.21014342,2.34358 0.20066442,2.896122 0.41300909,3.1219592 0.60816171,3.3295105 0.90177008,3.3453424 0.95593994,3.3503348 1.0177384,3.3560148 1.5339832,3.3499581 1.574996,3.351287 c 0.015313,4.929e-4 0.064365,0.00139 0.1311843,0.00287 0.027454,0.1558591 0.1348816,0.4055146 0.2891801,0.5079801 0.1737371,0.1153709 0.5840376,0.1672049 0.633898,0.1417174 0.033884,-0.017324 0.2120976,-0.020746 0.2120976,-0.03926 -3e-7,-0.00281 -0.1359618,-0.075872 -0.1795407,-0.098149 C 2.5715112,3.8202919 2.5190005,3.7242168 2.4506759,3.6543568 2.4244915,3.6275965 2.4279949,3.4751553 2.4315249,3.3742737 2.5495776,3.3733989 2.8697241,3.3839918 2.9371113,3.3838502 3.0975326,3.3835266 3.5689747,3.3993771 3.8080031,3.1818075 4.0962844,2.9193889 4.0228795,2.3969451 4.0186641,2.3267119 4.013119,2.2343213 4.0250025,1.6246294 4.0162732,1.4864616 4.0028561,1.274529 4.0737709,0.94594107 3.8376871,0.59402732 3.6199123,0.26941205 3.0597025,0.34195584 3.0151516,0.33931907 2.9077682,0.33296522 2.5794394,0.32573415 2.3616237,0.32495581 Z m 0.9580286,0.52713126 a 0.19209624,0.19209624 0 0 1 0.063678,0.007659 A 0.19209624,0.19209624 0 0 1 3.5121209,1.10057 c -0.019132,0.064024 -0.02934,0.114542 -0.029205,0.1517718 a 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.786e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.786e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.786e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 c -0.00327,0.073938 -0.00815,0.1281478 -0.00336,0.1646986 a 0.19211544,0.19211544 0 0 1 0.00192,0.01963 c 0.00122,0.044001 0.00215,0.096625 -0.00383,0.1560806 a 0.19211544,0.19211544 0 0 1 -0.0091,0.04309 c 0.00152,-0.00444 0.00292,-0.00713 0.00383,-0.00814 0.00239,4.689e-4 -5.16e-5,0.023556 -0.012927,0.069423 l -4.786e-4,0.00144 c -0.00322,0.018276 -0.00512,0.060008 -0.010052,0.1072455 2.1e-6,-1.573e-4 -1.8e-5,0.00348 0,0.00383 8.03e-5,0.00155 -1.3e-6,0.00456 0,0.016278 A 0.19209624,0.19209624 0 0 1 3.256933,2.0270008 0.19209624,0.19209624 0 0 1 3.0649443,1.835012 c -2e-7,-8.421e-4 -2.139e-4,-0.00933 0,-0.025375 a 0.19211544,0.19211544 0 0 1 0.00192,-0.021545 c 0.00393,-0.029738 0.00172,-0.085222 0.018193,-0.1627834 a 0.19211544,0.19211544 0 0 1 0.00336,-0.014841 c -0.00488,0.016544 -0.00842,-0.00696 0.0091,-0.066071 0.00128,-0.023365 8.374e-4,-0.05167 0,-0.083786 5.837e-4,0.00531 0.0012,0.010844 0.00192,0.016278 l -0.00192,-0.020109 c -0.00868,-0.082861 -0.00275,-0.1509043 0,-0.2044368 -3.839e-4,-0.1048643 0.02617,-0.1913531 0.047392,-0.26236915 A 0.19209624,0.19209624 0 0 1 3.3196523,0.85208707 Z M 3.097501,1.5443956 c -3.745e-4,0.00682 -8.326e-4,0.013152 -0.00144,0.019151 l 0.00862,-0.043569 c -0.00298,0.00868 -0.00496,0.016879 -0.00718,0.024418 z M 1.7483131,1.0129554 a 0.19211544,0.19211544 0 0 1 0.1804981,0.1292692 c 0.081754,0.230866 0.1671804,0.4503689 0.2566234,0.6094805 0.060542,-0.039278 0.13119,-0.081733 0.2374723,-0.083307 0.030189,-0.00505 0.059326,-0.01228 0.095756,-0.00527 0.053638,0.010328 0.1089723,0.045047 0.1426749,0.086658 0.067401,0.08322 0.064433,0.1543836 0.063678,0.2082669 -0.00151,0.1077673 -0.021788,0.2137733 -0.022023,0.2044369 A 0.19209624,0.19209624 0 0 1 2.5167468,2.3578344 0.19209624,0.19209624 0 0 1 2.3194915,2.1715908 c -7.704e-4,-0.030281 0.0031,-0.035159 0.00527,-0.059847 -0.035038,0.025653 -0.068601,0.053251 -0.1139486,0.081391 A 0.19211544,0.19211544 0 0 1 1.9704693,2.1624936 c -0.016009,-0.016679 -0.012719,-0.040218 -0.027291,-0.057933 -0.0053,0.038768 -0.013896,0.105592 -0.030642,0.1881586 -0.00975,0.048046 -0.018553,0.093357 -0.036386,0.1412386 -0.00891,0.023941 -0.00752,0.046058 -0.061283,0.09767 -0.00671,0.00645 -0.015395,0.013123 -0.025375,0.020109 -0.00997,0.00699 -0.03579,0.021291 -0.036386,0.021545 -0.00119,5.072e-4 -0.1089417,0.013114 -0.1101182,0.012927 -5.885e-4,-9.26e-5 -0.052085,-0.016004 -0.052666,-0.016278 -5.848e-4,-2.741e-4 -0.028877,-0.016619 -0.039745,-0.025375 -0.021733,-0.017517 -0.036349,-0.03491 -0.045484,-0.048835 a 0.19211544,0.19211544 0 0 1 -0.00718,-0.012927 C 1.405201,2.3135107 1.3718331,2.1230884 1.3226821,1.9293306 1.296257,1.9926645 1.2702556,2.0360279 1.236503,2.1127015 c -0.00662,0.020181 -0.015708,0.041777 -0.033514,0.067986 -0.021835,0.03214 -0.067722,0.078719 -0.1393236,0.090488 -0.0716015,0.011769 -0.13415192,-0.018894 -0.16469865,-0.043568 -0.0305472,-0.024673 -0.042975,-0.046717 -0.0541012,-0.065113 -0.0389429,-0.064387 -0.0578673,-0.09647 -0.0526653,-0.176189 0.002344,0.010422 0.004713,0.021014 0.00718,0.031599 L 0.79602584,1.94896 c -0.001684,0.013201 -0.003086,0.025254 -0.003828,0.036387 C 0.74313508,1.766609 0.72147035,1.582656 0.68734765,1.3720365 A 0.19209624,0.19209624 0 0 1 0.84486459,1.1527576 0.19209624,0.19209624 0 0 1 1.0655799,1.3102746 c 0.012592,0.077723 0.025291,0.1404024 0.035908,0.2097036 0.010745,-0.014664 0.00973,-0.026756 0.021545,-0.041175 -0.0011,-0.00222 0.032336,-0.054265 0.079956,-0.1067668 0.013605,-0.015001 0.028067,-0.03269 0.061762,-0.052665 0.033694,-0.019975 0.1078148,-0.047748 0.1843284,-0.018193 0.068698,0.026536 0.092715,0.077474 0.1086819,0.1139485 -0.00167,-0.078755 -0.00808,-0.1467436 -0.00383,-0.2207153 A 0.19211544,0.19211544 0 0 1 1.7186306,1.0153489 0.19211544,0.19211544 0 0 1 1.748314,1.0129564 Z M 1.2365027,2.1127015 c 0.0015,-0.00457 0.00304,-0.00894 0.00431,-0.013405 l -0.00862,0.02346 c 0.00152,-0.00352 0.00282,-0.00667 0.00431,-0.010052 z M 3.1899043,2.2683033 A 0.19374282,0.20281166 0 0 1 3.3833296,2.4713039 0.19374282,0.20281166 0 0 1 3.1899043,2.6743046 0.19374282,0.20281166 0 0 1 2.9960006,2.4713039 0.19374282,0.20281166 0 0 1 3.1899043,2.2683033 Z" + fill="#E0E0E0" /> + </g> +</svg> diff --git a/addons/dialogue_manager/assets/icon.svg.import b/addons/dialogue_manager/assets/icon.svg.import new file mode 100644 index 0000000..3b6fd5e --- /dev/null +++ b/addons/dialogue_manager/assets/icon.svg.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d3lr2uas6ax8v" +path="res://.godot/imported/icon.svg-17eb5d3e2a3cfbe59852220758c5b7bd.ctex" +metadata={ +"has_editor_variant": true, +"vram_texture": false +} + +[deps] + +source_file="res://addons/dialogue_manager/assets/icon.svg" +dest_files=["res://.godot/imported/icon.svg-17eb5d3e2a3cfbe59852220758c5b7bd.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=true +editor/convert_colors_with_editor_theme=true diff --git a/addons/dialogue_manager/assets/responses_menu.svg b/addons/dialogue_manager/assets/responses_menu.svg new file mode 100644 index 0000000..4e4089d --- /dev/null +++ b/addons/dialogue_manager/assets/responses_menu.svg @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="16" + height="16" + viewBox="0 0 4.2333333 4.2333335" + version="1.1" + id="svg291" + inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" + sodipodi:docname="responses_menu.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview293" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="px" + showgrid="false" + width="1920px" + units="px" + borderlayer="true" + inkscape:showpageshadow="false" + inkscape:deskcolor="#d1d1d1" + inkscape:zoom="45.254834" + inkscape:cx="7.8334173" + inkscape:cy="6.5959804" + inkscape:window-width="2560" + inkscape:window-height="1377" + inkscape:window-x="-8" + inkscape:window-y="-8" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + <defs + id="defs288" /> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + id="rect181" + style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:1.77487;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill" + d="M 1.5875 0.26458334 L 1.5875 0.79375001 L 4.2333334 0.79375001 L 4.2333334 0.26458334 L 1.5875 0.26458334 z M 0 0.83147381 L 0 2.4189738 L 1.3229167 1.6252238 L 0 0.83147381 z M 1.5875 1.3229167 L 1.5875 1.8520834 L 4.2333334 1.8520834 L 4.2333334 1.3229167 L 1.5875 1.3229167 z M 1.5875 2.38125 L 1.5875 2.9104167 L 4.2333334 2.9104167 L 4.2333334 2.38125 L 1.5875 2.38125 z M 1.5875 3.4395834 L 1.5875 3.9687501 L 4.2333334 3.9687501 L 4.2333334 3.4395834 L 1.5875 3.4395834 z " + fill="#E0E0E0" /> + </g> +</svg> diff --git a/addons/dialogue_manager/assets/responses_menu.svg.import b/addons/dialogue_manager/assets/responses_menu.svg.import new file mode 100644 index 0000000..83355fc --- /dev/null +++ b/addons/dialogue_manager/assets/responses_menu.svg.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://drjfciwitjm83" +path="res://.godot/imported/responses_menu.svg-87cf63ca685d53616205049572f4eb8f.ctex" +metadata={ +"has_editor_variant": true, +"vram_texture": false +} + +[deps] + +source_file="res://addons/dialogue_manager/assets/responses_menu.svg" +dest_files=["res://.godot/imported/responses_menu.svg-87cf63ca685d53616205049572f4eb8f.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=true +editor/convert_colors_with_editor_theme=true diff --git a/addons/dialogue_manager/assets/update.svg b/addons/dialogue_manager/assets/update.svg new file mode 100644 index 0000000..a5b80ee --- /dev/null +++ b/addons/dialogue_manager/assets/update.svg @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="300" + height="80" + viewBox="0 0 79.374999 21.166667" + version="1.1" + id="svg291" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + sodipodi:docname="update.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview293" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="px" + showgrid="false" + width="1920px" + units="px" + borderlayer="true" + inkscape:showpageshadow="false" + inkscape:zoom="1" + inkscape:cx="180.5" + inkscape:cy="111" + inkscape:window-width="1440" + inkscape:window-height="890" + inkscape:window-x="-6" + inkscape:window-y="-6" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:deskcolor="#d1d1d1" /> + <defs + id="defs288" /> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1" + id="rect2462" + width="13.228261" + height="9.4236727" + x="32.95359" + y="4.2143135" + ry="0.90020913" /> + <path + id="path3615" + style="clip-rule:evenodd;fill:#bd93f9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.52916667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:40;stroke-opacity:1;stroke-dasharray:none" + d="m 40.714378,3.0283624 c -0.297691,-0.00106 -0.546217,0.00208 -0.692956,0.00785 -1.220595,0.048091 -2.826171,0.059913 -3.83973,0.098152 -0.467403,0.017637 -3.048858,-0.2762743 -3.873101,0.7871837 -0.867561,1.1193864 -0.301209,6.2042409 -0.371018,6.9236829 -0.04459,0.459801 -0.08346,2.725309 0.787183,3.651277 0.800155,0.850991 2.003996,0.915905 2.2261,0.936375 0.253383,0.02331 2.370068,-0.0015 2.538226,0.0039 0.0628,0.002 0.263908,0.0057 0.537877,0.01177 0.112572,0.639046 0.553034,1.662672 1.185683,2.082798 0.712348,0.473037 2.394644,0.685566 2.599079,0.581063 0.138939,-0.07104 0.869634,-0.08507 0.869634,-0.160971 -2e-6,-0.01157 -0.557466,-0.311089 -0.736145,-0.402428 -0.370261,-0.189241 -0.585564,-0.583165 -0.865705,-0.869601 -0.107353,-0.109727 -0.09299,-0.734754 -0.07851,-1.148384 0.484034,-0.0035 1.796685,0.03983 2.072983,0.03926 0.657753,-0.0013 2.590738,0.06366 3.570791,-0.828408 1.181999,-1.075941 0.881027,-3.218042 0.863743,-3.50601 -0.02274,-0.378815 0.02599,-2.878646 -0.0098,-3.4451551 C 47.443688,6.9217592 47.734446,5.5744981 46.766467,4.1315973 45.873555,2.8006244 43.57661,3.0980651 43.393944,3.087254 42.953654,3.0612024 41.607455,3.0315527 40.714378,3.0283624 Z m 3.928065,2.1613198 a 0.78762433,0.78762433 0 0 1 0.261087,0.031405 0.78762433,0.78762433 0 0 1 0.528062,0.9874148 c -0.07845,0.2625075 -0.120302,0.46964 -0.119753,0.6222881 a 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 c -0.01334,0.3031554 -0.03341,0.5254256 -0.01373,0.6752895 a 0.78770308,0.78770308 0 0 1 0.0078,0.080487 c 0.0051,0.1804113 0.0088,0.3961799 -0.0157,0.6399549 a 0.78770308,0.78770308 0 0 1 -0.03726,0.1767104 c 0.0063,-0.018206 0.01197,-0.029244 0.0157,-0.033361 0.0098,0.00192 -2.12e-4,0.096583 -0.05301,0.2846419 l -0.002,0.00589 c -0.01314,0.074935 -0.02097,0.2460417 -0.04122,0.4397235 9e-6,-6.455e-4 -7.3e-5,0.014282 0,0.015695 3.29e-4,0.00634 -4e-6,0.018697 0,0.066743 A 0.78762433,0.78762433 0 0 1 44.385285,10.007011 0.78762433,0.78762433 0 0 1 43.598102,9.2198268 c -2e-6,-0.00345 -8.77e-4,-0.038262 0,-0.1040456 a 0.78770308,0.78770308 0 0 1 0.0078,-0.088337 c 0.01609,-0.12193 0.0071,-0.3494247 0.07459,-0.6674374 a 0.78770308,0.78770308 0 0 1 0.01373,-0.060853 c -0.02001,0.067835 -0.03455,-0.028543 0.03731,-0.270902 0.0053,-0.0958 0.0035,-0.2118566 0,-0.3435347 0.0024,0.021788 0.0049,0.044462 0.0078,0.066743 l -0.0078,-0.082447 c -0.03559,-0.3397458 -0.01118,-0.6187306 0,-0.8382225 -0.0016,-0.4299563 0.107334,-0.784574 0.194343,-1.0757507 A 0.78762433,0.78762433 0 0 1 44.642342,5.189683 Z m -0.910856,2.8385724 c -0.0015,0.027966 -0.0033,0.053926 -0.0059,0.078522 l 0.03533,-0.1786397 c -0.01216,0.035586 -0.02031,0.069207 -0.02945,0.100118 z M 38.199709,5.8492675 a 0.78770308,0.78770308 0 0 1 0.740071,0.5300233 c 0.335202,0.9465866 0.685464,1.8465826 1.052196,2.4989649 0.248233,-0.1610476 0.537898,-0.3351164 0.973672,-0.3415703 0.123774,-0.020676 0.243246,-0.050347 0.392613,-0.021583 0.219925,0.042345 0.446803,0.1847018 0.584989,0.3553102 0.276354,0.3412161 0.264185,0.6329968 0.261087,0.8539269 -0.0061,0.4418625 -0.08934,0.8765035 -0.09031,0.8382235 a 0.78762433,0.78762433 0 0 1 -0.763625,0.800915 0.78762433,0.78762433 0 0 1 -0.808777,-0.763625 c -0.0031,-0.124158 0.01275,-0.144159 0.02158,-0.245384 -0.143662,0.105178 -0.281267,0.218336 -0.467201,0.333717 a 0.78770308,0.78770308 0 0 1 -0.985442,-0.125632 c -0.06564,-0.06838 -0.05215,-0.164899 -0.111905,-0.237533 -0.0217,0.158952 -0.05697,0.432943 -0.125637,0.771479 -0.03994,0.196996 -0.07606,0.382777 -0.1492,0.579101 -0.03653,0.09815 -0.03084,0.18885 -0.251272,0.400462 -0.02751,0.02645 -0.06313,0.05381 -0.104038,0.08246 -0.04091,0.02866 -0.146748,0.0873 -0.1492,0.08834 -0.0049,0.0022 -0.446678,0.05377 -0.451502,0.05301 -0.0024,-3.79e-4 -0.213555,-0.06562 -0.215939,-0.06674 -0.0024,-0.0011 -0.118379,-0.06813 -0.162933,-0.104037 -0.08911,-0.07182 -0.149043,-0.143138 -0.186495,-0.20023 a 0.78770308,0.78770308 0 0 1 -0.02945,-0.05301 c -0.380095,-0.694111 -0.516908,-1.474871 -0.718435,-2.269308 -0.108354,0.2596787 -0.214957,0.437476 -0.353349,0.751849 -0.02715,0.08274 -0.06441,0.171293 -0.13741,0.278753 -0.08952,0.131779 -0.277668,0.322761 -0.571248,0.371015 -0.293578,0.04826 -0.550045,-0.07747 -0.67529,-0.178628 C 34.592013,10.728363 34.541064,10.63798 34.495437,10.562564 34.33576,10.298568 34.25817,10.167022 34.2795,9.8401611 c 0.0096,0.042731 0.01942,0.086159 0.02945,0.1295617 L 34.29521,9.6870414 c -0.0069,0.054124 -0.01275,0.1035434 -0.0157,0.1491901 C 34.07835,8.9393633 33.98952,8.1851278 33.849612,7.3215552 a 0.78762433,0.78762433 0 0 1 0.645844,-0.8990776 0.78762433,0.78762433 0 0 1 0.904966,0.645844 c 0.05164,0.3186785 0.103704,0.5756714 0.147218,0.859817 0.04404,-0.060125 0.03987,-0.1097017 0.08834,-0.1688245 -0.0045,-0.0091 0.132583,-0.2224951 0.327832,-0.4377603 0.05578,-0.061504 0.115083,-0.1340347 0.253236,-0.2159342 0.138154,-0.081904 0.442057,-0.1957766 0.755775,-0.074598 0.281673,0.1088032 0.380145,0.3176572 0.445613,0.4672063 -0.0069,-0.3229043 -0.03312,-0.6016714 -0.0157,-0.9049667 a 0.78770308,0.78770308 0 0 1 0.675286,-0.7341808 0.78770308,0.78770308 0 0 1 0.121714,-0.00981 z m -2.098502,4.5091295 c 0.0061,-0.01874 0.01255,-0.03666 0.01766,-0.05496 l -0.03533,0.09619 c 0.0063,-0.01442 0.01158,-0.02735 0.01766,-0.04123 z m 8.00925,0.63799 a 0.79437562,0.83155922 0 0 1 0.793073,0.832334 0.79437562,0.83155922 0 0 1 -0.793073,0.832335 0.79437562,0.83155922 0 0 1 -0.795036,-0.832335 0.79437562,0.83155922 0 0 1 0.795036,-0.832334 z" /> + <path + id="path2353" + style="clip-rule:evenodd;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#4d425c;stroke-width:0.529167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:40;stroke-dasharray:none;stroke-opacity:1" + d="m 40.538948,3.0282389 c -0.29769,-0.00106 -0.546242,0.00198 -0.692981,0.00775 -1.220593,0.048091 -2.826517,0.059946 -3.840075,0.098185 -0.467403,0.017637 -3.048907,-0.2759081 -3.873149,0.7875489 -0.86756,1.1193852 -0.300711,6.2041675 -0.37052,6.9236085 -0.04459,0.4598 -0.08361,2.724973 0.787032,3.65094 0.800154,0.85099 2.004117,0.915907 2.226221,0.936377 0.253382,0.02331 2.369672,-0.0013 2.537829,0.0041 0.0628,0.002 0.263983,0.0058 0.537952,0.01189 0.112572,0.639046 0.553326,1.662435 1.185974,2.082561 0.712347,0.473036 2.394373,0.685862 2.598808,0.58136 0.138939,-0.07104 0.869714,-0.08533 0.869714,-0.161231 -2e-6,-0.01157 -0.55771,-0.31122 -0.736389,-0.402559 -0.370261,-0.189241 -0.585439,-0.582762 -0.86558,-0.869198 -0.107353,-0.109727 -0.09303,-0.735137 -0.07855,-1.148767 0.484033,-0.0035 1.79696,0.03984 2.073258,0.03927 0.657752,-0.0013 2.59079,0.06369 3.570842,-0.828373 1.181997,-1.07594 0.880797,-3.217762 0.863513,-3.505729 -0.02274,-0.378815 0.02597,-2.8787595 -0.0098,-3.4452681 C 47.268006,6.9217821 47.558753,5.5744301 46.590775,4.1315308 45.697864,2.8005592 43.401037,3.0979612 43.218371,3.0871501 42.778082,3.0610985 41.432024,3.0314292 40.538948,3.0282389 Z" /> + <path + id="rect1625" + style="fill:#50fa7b;fill-opacity:1;stroke:#0f451d;stroke-width:0.593381;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" + d="m 50.52517,5.3570989 c -0.643062,0 -1.160653,0.5900216 -1.160653,1.3229166 v 1.0764201 h -1.07642 c -0.732895,0 -1.322916,0.5175908 -1.322916,1.1606533 0,0.643061 0.590021,1.1611691 1.322916,1.1611691 h 1.07642 v 1.076421 c 0,0.732895 0.517591,1.322917 1.160653,1.322917 0.643062,0 1.160653,-0.590022 1.160653,-1.322917 v -1.076421 h 1.076937 c 0.732895,0 1.322916,-0.5181081 1.322916,-1.1611691 0,-0.6430625 -0.590021,-1.1606533 -1.322916,-1.1606533 H 51.685823 V 6.6800155 c 0,-0.732895 -0.517591,-1.3229166 -1.160653,-1.3229166 z" /> + <path + id="path2678" + style="fill:#50fa7b;fill-opacity:1;stroke:#0f451d;stroke-width:0.593381;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" + d="m 57.791691,5.357099 c -0.643062,0 -1.160653,0.5900216 -1.160653,1.3229166 v 1.0764201 h -1.07642 c -0.732895,0 -1.322916,0.5175908 -1.322916,1.1606522 0,0.643062 0.590021,1.1611701 1.322916,1.1611701 h 1.07642 v 1.076421 c 0,0.732895 0.517591,1.322917 1.160653,1.322917 0.643062,0 1.160653,-0.590022 1.160653,-1.322917 v -1.076421 h 1.076937 c 0.732895,0 1.322916,-0.5181081 1.322916,-1.1611701 0,-0.6430614 -0.590021,-1.1606522 -1.322916,-1.1606522 H 58.952344 V 6.6800156 c 0,-0.732895 -0.517591,-1.3229166 -1.160653,-1.3229166 z" /> + </g> +</svg> diff --git a/addons/dialogue_manager/assets/update.svg.import b/addons/dialogue_manager/assets/update.svg.import new file mode 100644 index 0000000..2d8171a --- /dev/null +++ b/addons/dialogue_manager/assets/update.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d3baj6rygkb3f" +path="res://.godot/imported/update.svg-f1628866ed4eb2e13e3b81f75443687e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/dialogue_manager/assets/update.svg" +dest_files=["res://.godot/imported/update.svg-f1628866ed4eb2e13e3b81f75443687e.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 diff --git a/addons/dialogue_manager/components/code_edit.gd b/addons/dialogue_manager/components/code_edit.gd new file mode 100644 index 0000000..e57c1af --- /dev/null +++ b/addons/dialogue_manager/components/code_edit.gd @@ -0,0 +1,425 @@ +@tool +extends CodeEdit + + +signal active_title_change(title: String) +signal error_clicked(line_number: int) +signal external_file_requested(path: String, title: String) + + +const DialogueSyntaxHighlighter = preload("./code_edit_syntax_highlighter.gd") + + +# A link back to the owner MainView +var main_view + +# Theme overrides for syntax highlighting, etc +var theme_overrides: Dictionary: + set(value): + theme_overrides = value + + syntax_highlighter = DialogueSyntaxHighlighter.new() + + # General UI + add_theme_color_override("font_color", theme_overrides.text_color) + add_theme_color_override("background_color", theme_overrides.background_color) + add_theme_color_override("current_line_color", theme_overrides.current_line_color) + add_theme_font_override("font", get_theme_font("source", "EditorFonts")) + add_theme_font_size_override("font_size", theme_overrides.font_size * theme_overrides.scale) + font_size = round(theme_overrides.font_size) + get: + return theme_overrides + +# Any parse errors +var errors: Array: + set(next_errors): + errors = next_errors + for i in range(0, get_line_count()): + var is_error: bool = false + for error in errors: + if error.line_number == i: + is_error = true + mark_line_as_error(i, is_error) + _on_code_edit_caret_changed() + get: + return errors + +# The last selection (if there was one) so we can remember it for refocusing +var last_selected_text: String + +var font_size: int: + set(value): + font_size = value + add_theme_font_size_override("font_size", font_size * theme_overrides.scale) + get: + return font_size + +var WEIGHTED_RANDOM_PREFIX: RegEx = RegEx.create_from_string("^\\%[\\d.]+\\s") + + +func _ready() -> void: + # Add error gutter + add_gutter(0) + set_gutter_type(0, TextEdit.GUTTER_TYPE_ICON) + + # Add comment delimiter + if not has_comment_delimiter("#"): + add_comment_delimiter("#", "", true) + + syntax_highlighter = DialogueSyntaxHighlighter.new() + + +func _gui_input(event: InputEvent) -> void: + if event is InputEventKey and event.is_pressed(): + match event.as_text(): + "Ctrl+Equal", "Command+Equal": + self.font_size += 1 + get_viewport().set_input_as_handled() + "Ctrl+Minus", "Command+Minus": + self.font_size -= 1 + get_viewport().set_input_as_handled() + "Ctrl+0", "Command+0": + self.font_size = theme_overrides.font_size + get_viewport().set_input_as_handled() + "Ctrl+K", "Command+K": + toggle_comment() + get_viewport().set_input_as_handled() + "Alt+Up": + move_line(-1) + get_viewport().set_input_as_handled() + "Alt+Down": + move_line(1) + get_viewport().set_input_as_handled() + + elif event is InputEventMouse: + match event.as_text(): + "Ctrl+Mouse Wheel Up", "Command+Mouse Wheel Up": + self.font_size += 1 + get_viewport().set_input_as_handled() + "Ctrl+Mouse Wheel Down", "Command+Mouse Wheel Down": + self.font_size -= 1 + get_viewport().set_input_as_handled() + + +func _can_drop_data(at_position: Vector2, data) -> bool: + if typeof(data) != TYPE_DICTIONARY: return false + if data.type != "files": return false + + var files: PackedStringArray = Array(data.files).filter(func(f): return f.get_extension() == "dialogue") + return files.size() > 0 + + +func _drop_data(at_position: Vector2, data) -> void: + var replace_regex: RegEx = RegEx.create_from_string("[^a-zA-Z_0-9]+") + + var files: PackedStringArray = Array(data.files).filter(func(f): return f.get_extension() == "dialogue") + for file in files: + # Don't import the file into itself + if file == main_view.current_file_path: continue + + var path = file.replace("res://", "").replace(".dialogue", "") + # Find the first non-import line in the file to add our import + var lines = text.split("\n") + for i in range(0, lines.size()): + if not lines[i].begins_with("import "): + insert_line_at(i, "import \"%s\" as %s\n" % [file, replace_regex.sub(path, "_", true)]) + set_caret_line(i) + break + + +func _request_code_completion(force: bool) -> void: + var cursor: Vector2 = get_cursor() + var current_line: String = get_line(cursor.y) + + if ("=> " in current_line or "=>< " in current_line) and (cursor.x > current_line.find("=>")): + var prompt: String = current_line.split("=>")[1] + if prompt.begins_with("< "): + prompt = prompt.substr(2) + else: + prompt = prompt.substr(1) + + if "=> " in current_line: + if matches_prompt(prompt, "end"): + add_code_completion_option(CodeEdit.KIND_CLASS, "END", "END".substr(prompt.length()), theme_overrides.text_color, get_theme_icon("Stop", "EditorIcons")) + if matches_prompt(prompt, "end!"): + add_code_completion_option(CodeEdit.KIND_CLASS, "END!", "END!".substr(prompt.length()), theme_overrides.text_color, get_theme_icon("Stop", "EditorIcons")) + + # Get all titles, including those in imports + var parser: DialogueManagerParser = DialogueManagerParser.new() + parser.prepare(text, main_view.current_file_path, false) + for title in parser.titles: + if "/" in title: + var bits = title.split("/") + if matches_prompt(prompt, bits[0]) or matches_prompt(prompt, bits[1]): + add_code_completion_option(CodeEdit.KIND_CLASS, title, title.substr(prompt.length()), theme_overrides.text_color, get_theme_icon("CombineLines", "EditorIcons")) + elif matches_prompt(prompt, title): + add_code_completion_option(CodeEdit.KIND_CLASS, title, title.substr(prompt.length()), theme_overrides.text_color, get_theme_icon("ArrowRight", "EditorIcons")) + update_code_completion_options(true) + parser.free() + return + + var name_so_far: String = WEIGHTED_RANDOM_PREFIX.sub(current_line.strip_edges(), "") + if name_so_far != "" and name_so_far[0].to_upper() == name_so_far[0]: + # Only show names starting with that character + var names: PackedStringArray = get_character_names(name_so_far) + if names.size() > 0: + for name in names: + add_code_completion_option(CodeEdit.KIND_CLASS, name + ": ", name.substr(name_so_far.length()) + ": ", theme_overrides.text_color, get_theme_icon("Sprite2D", "EditorIcons")) + update_code_completion_options(true) + else: + cancel_code_completion() + + +func _filter_code_completion_candidates(candidates: Array) -> Array: + # Not sure why but if this method isn't overridden then all completions are wrapped in quotes. + return candidates + + +func _confirm_code_completion(replace: bool) -> void: + var completion = get_code_completion_option(get_code_completion_selected_index()) + begin_complex_operation() + # Delete any part of the text that we've already typed + for i in range(0, completion.display_text.length() - completion.insert_text.length()): + backspace() + # Insert the whole match + insert_text_at_caret(completion.display_text) + end_complex_operation() + + # Close the autocomplete menu on the next tick + call_deferred("cancel_code_completion") + + +### Helpers + + +# Get the current caret as a Vector2 +func get_cursor() -> Vector2: + return Vector2(get_caret_column(), get_caret_line()) + + +# Set the caret from a Vector2 +func set_cursor(from_cursor: Vector2) -> void: + set_caret_line(from_cursor.y) + set_caret_column(from_cursor.x) + + +# Check if a prompt is the start of a string without actually being that string +func matches_prompt(prompt: String, matcher: String) -> bool: + return prompt.length() < matcher.length() and matcher.to_lower().begins_with(prompt.to_lower()) + + +## Get a list of titles from the current text +func get_titles() -> PackedStringArray: + var titles = PackedStringArray([]) + var lines = text.split("\n") + for line in lines: + if line.begins_with("~ "): + titles.append(line.substr(2).strip_edges()) + return titles + + +## Work out what the next title above the current line is +func check_active_title() -> void: + var line_number = get_caret_line() + var lines = text.split("\n") + # Look at each line above this one to find the next title line + for i in range(line_number, -1, -1): + if lines[i].begins_with("~ "): + active_title_change.emit(lines[i].replace("~ ", "")) + return + + active_title_change.emit("") + + +# Move the caret line to match a given title +func go_to_title(title: String) -> void: + var lines = text.split("\n") + for i in range(0, lines.size()): + if lines[i].strip_edges() == "~ " + title: + set_caret_line(i) + center_viewport_to_caret() + + +func get_character_names(beginning_with: String) -> PackedStringArray: + var names: PackedStringArray = [] + var lines = text.split("\n") + for line in lines: + if ": " in line: + var name: String = WEIGHTED_RANDOM_PREFIX.sub(line.split(": ")[0].strip_edges(), "") + if not name in names and matches_prompt(beginning_with, name): + names.append(name) + return names + + +# Mark a line as an error or not +func mark_line_as_error(line_number: int, is_error: bool) -> void: + if is_error: + set_line_background_color(line_number, theme_overrides.error_line_color) + set_line_gutter_icon(line_number, 0, get_theme_icon("StatusError", "EditorIcons")) + else: + set_line_background_color(line_number, theme_overrides.background_color) + set_line_gutter_icon(line_number, 0, null) + + +# Insert or wrap some bbcode at the caret/selection +func insert_bbcode(open_tag: String, close_tag: String = "") -> void: + if close_tag == "": + insert_text_at_caret(open_tag) + grab_focus() + else: + var selected_text = get_selected_text() + insert_text_at_caret("%s%s%s" % [open_tag, selected_text, close_tag]) + grab_focus() + set_caret_column(get_caret_column() - close_tag.length()) + +# Insert text at current caret position +# Move Caret down 1 line if not => END +func insert_text(text: String) -> void: + if text != "=> END": + insert_text_at_caret(text+"\n") + set_caret_line(get_caret_line()+1) + else: + insert_text_at_caret(text) + grab_focus() + + +# Toggle the selected lines as comments +func toggle_comment() -> void: + begin_complex_operation() + + var comment_delimiter: String = delimiter_comments[0] + var is_first_line: bool = true + var will_comment: bool = true + var selections: Array = [] + var line_offsets: Dictionary = {} + + for caret_index in range(0, get_caret_count()): + var from_line: int = get_caret_line(caret_index) + var from_column: int = get_caret_column(caret_index) + var to_line: int = get_caret_line(caret_index) + var to_column: int = get_caret_column(caret_index) + + if has_selection(caret_index): + from_line = get_selection_from_line(caret_index) + to_line = get_selection_to_line(caret_index) + from_column = get_selection_from_column(caret_index) + to_column = get_selection_to_column(caret_index) + + selections.append({ + from_line = from_line, + from_column = from_column, + to_line = to_line, + to_column = to_column + }) + + for line_number in range(from_line, to_line + 1): + if line_offsets.has(line_number): continue + + var line_text: String = get_line(line_number) + + # The first line determines if we are commenting or uncommentingg + if is_first_line: + is_first_line = false + will_comment = not line_text.strip_edges().begins_with(comment_delimiter) + + # Only comment/uncomment if the current line needs to + if will_comment: + set_line(line_number, comment_delimiter + line_text) + line_offsets[line_number] = 1 + elif line_text.begins_with(comment_delimiter): + set_line(line_number, line_text.substr(comment_delimiter.length())) + line_offsets[line_number] = -1 + else: + line_offsets[line_number] = 0 + + for caret_index in range(0, get_caret_count()): + var selection: Dictionary = selections[caret_index] + select( + selection.from_line, + selection.from_column + line_offsets[selection.from_line], + selection.to_line, + selection.to_column + line_offsets[selection.to_line], + caret_index + ) + set_caret_column(selection.from_column + line_offsets[selection.from_line], false, caret_index) + + end_complex_operation() + + text_set.emit() + text_changed.emit() + + +# Move the selected lines up or down +func move_line(offset: int) -> void: + offset = clamp(offset, -1, 1) + + var cursor = get_cursor() + var reselect: bool = false + var from: int = cursor.y + var to: int = cursor.y + if has_selection(): + reselect = true + from = get_selection_from_line() + to = get_selection_to_line() + + var lines := text.split("\n") + + # We can't move the lines out of bounds + if from + offset < 0 or to + offset >= lines.size(): return + + var target_from_index = from - 1 if offset == -1 else to + 1 + var target_to_index = to if offset == -1 else from + var line_to_move = lines[target_from_index] + lines.remove_at(target_from_index) + lines.insert(target_to_index, line_to_move) + + text = "\n".join(lines) + + cursor.y += offset + from += offset + to += offset + if reselect: + select(from, 0, to, get_line_width(to)) + set_cursor(cursor) + text_changed.emit() + + +### Signals + + +func _on_code_edit_symbol_validate(symbol: String) -> void: + if symbol.begins_with("res://") and symbol.ends_with(".dialogue"): + set_symbol_lookup_word_as_valid(true) + return + + for title in get_titles(): + if symbol == title: + set_symbol_lookup_word_as_valid(true) + return + set_symbol_lookup_word_as_valid(false) + + +func _on_code_edit_symbol_lookup(symbol: String, line: int, column: int) -> void: + if symbol.begins_with("res://") and symbol.ends_with(".dialogue"): + external_file_requested.emit(symbol, "") + else: + go_to_title(symbol) + + +func _on_code_edit_text_changed() -> void: + request_code_completion(true) + + +func _on_code_edit_text_set() -> void: + queue_redraw() + + +func _on_code_edit_caret_changed() -> void: + check_active_title() + last_selected_text = get_selected_text() + + +func _on_code_edit_gutter_clicked(line: int, gutter: int) -> void: + var line_errors = errors.filter(func(error): return error.line_number == line) + if line_errors.size() > 0: + error_clicked.emit(line) diff --git a/addons/dialogue_manager/components/code_edit.tscn b/addons/dialogue_manager/components/code_edit.tscn new file mode 100644 index 0000000..a974ea3 --- /dev/null +++ b/addons/dialogue_manager/components/code_edit.tscn @@ -0,0 +1,56 @@ +[gd_scene load_steps=4 format=3 uid="uid://civ6shmka5e8u"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit_syntax_highlighter.gd" id="1_58cfo"] +[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit.gd" id="1_g324i"] + +[sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_cobxx"] +script = ExtResource("1_58cfo") + +[node name="CodeEdit" type="CodeEdit"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +text = "~ title_thing + +if this = \"that\" or 'this' +Nathan: Something +- Then [if test.thing() == 2.0] => somewhere +- Other => END! + +~ somewhere + +set has_something = true +=> END" +highlight_all_occurrences = true +highlight_current_line = true +draw_tabs = true +syntax_highlighter = SubResource("SyntaxHighlighter_cobxx") +scroll_past_end_of_file = true +minimap_draw = true +symbol_lookup_on_click = true +line_folding = true +gutters_draw_line_numbers = true +gutters_draw_fold_gutter = true +delimiter_strings = Array[String](["\" \""]) +delimiter_comments = Array[String](["#"]) +code_completion_enabled = true +code_completion_prefixes = Array[String]([">", "<"]) +indent_automatic = true +auto_brace_completion_enabled = true +auto_brace_completion_highlight_matching = true +auto_brace_completion_pairs = { +"\"": "\"", +"(": ")", +"[": "]", +"{": "}" +} +script = ExtResource("1_g324i") + +[connection signal="caret_changed" from="." to="." method="_on_code_edit_caret_changed"] +[connection signal="gutter_clicked" from="." to="." method="_on_code_edit_gutter_clicked"] +[connection signal="symbol_lookup" from="." to="." method="_on_code_edit_symbol_lookup"] +[connection signal="symbol_validate" from="." to="." method="_on_code_edit_symbol_validate"] +[connection signal="text_changed" from="." to="." method="_on_code_edit_text_changed"] +[connection signal="text_set" from="." to="." method="_on_code_edit_text_set"] diff --git a/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd b/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd new file mode 100644 index 0000000..fe1b8bd --- /dev/null +++ b/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd @@ -0,0 +1,382 @@ +@tool +extends SyntaxHighlighter + + +enum ExpressionType {DO, SET, IF} + + +var dialogue_manager_parser: DialogueManagerParser = DialogueManagerParser.new() + +var regex_titles: RegEx = RegEx.create_from_string("^\\s*(?<title>~\\s+[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+)") +var regex_comments: RegEx = RegEx.create_from_string("(?:(?>\"(?:\\\\\"|[^\"\\n])*\")[^\"\\n]*?\\s*(?<comment>#[^\\n]*)$|^[^\"#\\n]*?\\s*(?<comment2>#[^\\n]*))") +var regex_mutation: RegEx = RegEx.create_from_string("^\\s*(do|do!|set) (?<mutation>.*)") +var regex_condition: RegEx = RegEx.create_from_string("^\\s*(if|elif|while|else if) (?<condition>.*)") +var regex_wcondition: RegEx = RegEx.create_from_string("\\[if (?<condition>((?:[^\\[\\]]*)|(?:\\[(?1)\\]))*?)\\]") +var regex_wendif: RegEx = RegEx.create_from_string("\\[(\\/if|else)\\]") +var regex_rgroup: RegEx = RegEx.create_from_string("\\[\\[(?<options>.*?)\\]\\]") +var regex_endconditions: RegEx = RegEx.create_from_string("^\\s*(endif|else):?\\s*$") +var regex_tags: RegEx = RegEx.create_from_string("\\[(?<tag>(?!(?:ID:.*)|if)[a-zA-Z_][a-zA-Z0-9_]*!?)(?:[= ](?<val>[^\\[\\]]+))?\\](?:(?<text>(?!\\[\\/\\k<tag>\\]).*?)?(?<end>\\[\\/\\k<tag>\\]))?") +var regex_dialogue: RegEx = RegEx.create_from_string("^\\s*(?:(?<random>\\%[\\d.]* )|(?<response>- ))?(?:(?<character>[^#:]*): )?(?<dialogue>.*)$") +var regex_goto: RegEx = RegEx.create_from_string("=><? (?:(?<file>[^\\/]+)\\/)?(?<title>[^\\/]*)") +var regex_string: RegEx = RegEx.create_from_string("^(?<delimiter>[\"'])(?<content>(?:\\\\{2})*|(?:.*?[^\\\\](?:\\\\{2})*))\\1$") +var regex_escape: RegEx = RegEx.create_from_string("\\\\.") +var regex_number: RegEx = RegEx.create_from_string("^-?(?:(?:0x(?:[0-9A-Fa-f]{2})+)|(?:0b[01]+)|(?:\\d+(?:(?:[\\.]\\d*)?(?:e\\d+)?)|(?:_\\d+)+)?)$") +var regex_array: RegEx = RegEx.create_from_string("\\[((?>[^\\[\\]]+|(?R))*)\\]") +var regex_dict: RegEx = RegEx.create_from_string("^\\{((?>[^\\{\\}]+|(?R))*)\\}$") +var regex_kvdict: RegEx = RegEx.create_from_string("^\\s*(?<left>.*?)\\s*(?<colon>:|=)\\s*(?<right>[^\\/]+)$") +var regex_commas: RegEx = RegEx.create_from_string("([^,]+)(?:\\s*,\\s*)?") +var regex_assignment: RegEx = RegEx.create_from_string("^\\s*(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*(?<op>(?:\\/|\\*|-|\\+)?=)\\s*(?<val>.*)$") +var regex_varname: RegEx = RegEx.create_from_string("^\\s*(?!true|false|and|or|not|in|null)(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*$") +var regex_keyword: RegEx = RegEx.create_from_string("^\\s*(true|false|null)\\s*$") +var regex_function: RegEx = RegEx.create_from_string("^\\s*([a-zA-Z_][a-zA-Z_0-9]*\\s*)\\(") +var regex_comparison: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s*(?<op>==|>=|<=|<|>|!=)\\s*(?<right>.*)$") +var regex_blogical: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s+(?<op>and|or|in)\\s+(?<right>.*)$") +var regex_ulogical: RegEx = RegEx.create_from_string("^\\s*(?<op>not)\\s+(?<right>.*)$") +var regex_paren: RegEx = RegEx.create_from_string("\\((?<paren>((?:[^\\(\\)]*)|(?:\\((?1)\\)))*?)\\)") + +var cache: Dictionary = {} + + +func _notification(what: int) -> void: + if what == NOTIFICATION_PREDELETE: + dialogue_manager_parser.free() + + +func _clear_highlighting_cache() -> void: + cache = {} + + +## Returns the syntax coloring for a dialogue file line +func _get_line_syntax_highlighting(line: int) -> Dictionary: + var colors: Dictionary = {} + var text_edit: TextEdit = get_text_edit() + var text: String = text_edit.get_line(line) + + # Prevents an error from popping up while developing + if not is_instance_valid(text_edit) or text_edit.theme_overrides.is_empty(): + return colors + + # Disable this, as well as the line at the bottom of this function to remove the cache. + if text in cache: + return cache[text] + + # Comments, we have to remove them at this point so the rest of the processing is easier + # Counts both end-of-line and single-line comments + # Comments are not allowed within dialogue lines or response lines, so we ask the parser what it thinks the current line is + if not (dialogue_manager_parser.is_dialogue_line(text) or dialogue_manager_parser.is_response_line(text)) or dialogue_manager_parser.is_line_empty(text) or dialogue_manager_parser.is_import_line(text): + var comment_matches: Array[RegExMatch] = regex_comments.search_all(text) + for comment_match in comment_matches: + for i in ["comment", "comment2"]: + if i in comment_match.names: + colors[comment_match.get_start(i)] = {"color": text_edit.theme_overrides.comments_color} + text = text.substr(0, comment_match.get_start(i)) + + # Dialogues. + var dialogue_matches: Array[RegExMatch] = regex_dialogue.search_all(text) + for dialogue_match in dialogue_matches: + if "random" in dialogue_match.names: + colors[dialogue_match.get_start("random")] = {"color": text_edit.theme_overrides.symbols_color} + colors[dialogue_match.get_end("random")] = {"color": text_edit.theme_overrides.text_color} + if "response" in dialogue_match.names: + colors[dialogue_match.get_start("response")] = {"color": text_edit.theme_overrides.symbols_color} + colors[dialogue_match.get_end("response")] = {"color": text_edit.theme_overrides.text_color} + if "character" in dialogue_match.names: + colors[dialogue_match.get_start("character")] = {"color": text_edit.theme_overrides.members_color} + colors[dialogue_match.get_end("character")] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_dialogue_syntax_highlighting(dialogue_match.get_start("dialogue"), dialogue_match.get_string("dialogue")), true) + + # Title lines. + if dialogue_manager_parser.is_title_line(text): + var title_matches: Array[RegExMatch] = regex_titles.search_all(text) + for title_match in title_matches: + colors[title_match.get_start("title")] = {"color": text_edit.theme_overrides.titles_color} + + # Import lines. + var import_matches: Array[RegExMatch] = dialogue_manager_parser.IMPORT_REGEX.search_all(text) + for import_match in import_matches: + colors[import_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} + colors[import_match.get_start("path") - 1] = {"color": text_edit.theme_overrides.strings_color} + colors[import_match.get_end("path") + 1] = {"color": text_edit.theme_overrides.conditions_color} + colors[import_match.get_start("prefix")] = {"color": text_edit.theme_overrides.members_color} + colors[import_match.get_end("prefix")] = {"color": text_edit.theme_overrides.conditions_color} + + # Using clauses + var using_matches: Array[RegExMatch] = dialogue_manager_parser.USING_REGEX.search_all(text) + for using_match in using_matches: + colors[using_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} + colors[using_match.get_start("state") - 1] = {"color": text_edit.theme_overrides.text_color} + + # Condition keywords and expressions. + var condition_matches: Array[RegExMatch] = regex_condition.search_all(text) + for condition_match in condition_matches: + colors[condition_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} + colors[condition_match.get_end(1)] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_expression_syntax_highlighting(condition_match.get_start("condition"), ExpressionType.IF, condition_match.get_string("condition")), true) + # endif/else + var endcondition_matches: Array[RegExMatch] = regex_endconditions.search_all(text) + for endcondition_match in endcondition_matches: + colors[endcondition_match.get_start(1)] = {"color": text_edit.theme_overrides.conditions_color} + colors[endcondition_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + + # Mutations. + var mutation_matches: Array[RegExMatch] = regex_mutation.search_all(text) + for mutation_match in mutation_matches: + colors[mutation_match.get_start(0)] = {"color": text_edit.theme_overrides.mutations_color} + colors.merge(_get_expression_syntax_highlighting(mutation_match.get_start("mutation"), ExpressionType.DO if mutation_match.strings[1] == "do" else ExpressionType.SET, mutation_match.get_string("mutation")), true) + + # CodeEdit seems to have issues if the Dictionary keys weren't added in order? + var new_colors: Dictionary = {} + var ordered_keys: Array = colors.keys() + ordered_keys.sort() + for index in ordered_keys: + new_colors[index] = colors[index] + + cache[text] = new_colors + return new_colors + + +## Returns the syntax highlighting for a dialogue line +func _get_dialogue_syntax_highlighting(start_index: int, text: String) -> Dictionary: + var text_edit: TextEdit = get_text_edit() + var colors: Dictionary = {} + + # #tag style tags + var hashtag_matches: Array[RegExMatch] = dialogue_manager_parser.TAGS_REGEX.search_all(text) + for hashtag_match in hashtag_matches: + colors[start_index + hashtag_match.get_start(0)] = { "color": text_edit.theme_overrides.comments_color } + colors[start_index + hashtag_match.get_end(0)] = { "color": text_edit.theme_overrides.text_color } + + # Global tags, like bbcode. + var tag_matches: Array[RegExMatch] = regex_tags.search_all(text) + for tag_match in tag_matches: + colors[start_index + tag_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + if "val" in tag_match.names: + colors.merge(_get_literal_syntax_highlighting(start_index + tag_match.get_start("val"), tag_match.get_string("val")), true) + colors[start_index + tag_match.get_end("val")] = {"color": text_edit.theme_overrides.symbols_color} + # Showing the text color straight in the editor for better ease-of-use + if tag_match.get_string("tag") == "color": + colors[start_index + tag_match.get_start("val")] = {"color": Color.from_string(tag_match.get_string("val"), text_edit.theme_overrides.text_color)} + if "text" in tag_match.names: + colors[start_index + tag_match.get_start("text")] = {"color": text_edit.theme_overrides.text_color} + # Text can still contain tags if several effects are applied ([center][b]Something[/b][/center], so recursing + colors.merge(_get_dialogue_syntax_highlighting(start_index + tag_match.get_start("text"), tag_match.get_string("text")), true) + colors[start_index + tag_match.get_end("text")] = {"color": text_edit.theme_overrides.symbols_color} + if "end" in tag_match.names: + colors[start_index + tag_match.get_start("end")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + tag_match.get_end("end")] = {"color": text_edit.theme_overrides.text_color} + colors[start_index + tag_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + # ID tag. + var translation_matches: Array[RegExMatch] = dialogue_manager_parser.TRANSLATION_REGEX.search_all(text) + for translation_match in translation_matches: + colors[start_index + translation_match.get_start(0)] = {"color": text_edit.theme_overrides.comments_color} + colors[start_index + translation_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + # Replacements. + var replacement_matches: Array[RegExMatch] = dialogue_manager_parser.REPLACEMENTS_REGEX.search_all(text) + for replacement_match in replacement_matches: + colors[start_index + replacement_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + replacement_match.get_start(1)] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + replacement_match.get_start(1), replacement_match.strings[1]), true) + colors[start_index + replacement_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + replacement_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + # Jump at the end of a response. + var goto_matches: Array[RegExMatch] = regex_goto.search_all(text) + for goto_match in goto_matches: + colors[start_index + goto_match.get_start(0)] = {"color": text_edit.theme_overrides.jumps_color} + if "file" in goto_match.names: + colors[start_index + goto_match.get_start("file")] = {"color": text_edit.theme_overrides.members_color} + colors[start_index + goto_match.get_end("file")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + goto_match.get_start("title")] = {"color": text_edit.theme_overrides.titles_color} + colors[start_index + goto_match.get_end("title")] = {"color": text_edit.theme_overrides.jumps_color} + colors[start_index + goto_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + # Wrapped condition. + var wcondition_matches: Array[RegExMatch] = regex_wcondition.search_all(text) + for wcondition_match in wcondition_matches: + colors[start_index + wcondition_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + wcondition_match.get_start(0) + 1] = {"color": text_edit.theme_overrides.conditions_color} + colors[start_index + wcondition_match.get_start(0) + 3] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + wcondition_match.get_start("condition"), wcondition_match.get_string("condition")), true) + colors[start_index + wcondition_match.get_end("condition")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + wcondition_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + # [/if] tag for color matching with the opening tag + var wendif_matches: Array[RegExMatch] = regex_wendif.search_all(text) + for wendif_match in wendif_matches: + colors[start_index + wendif_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + wendif_match.get_start(1)] = {"color": text_edit.theme_overrides.conditions_color} + colors[start_index + wendif_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + wendif_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + # Random groups + var rgroup_matches: Array[RegExMatch] = regex_rgroup.search_all(text) + for rgroup_match in rgroup_matches: + colors[start_index + rgroup_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + rgroup_match.get_start("options")] = {"color": text_edit.theme_overrides.text_color} + var separator_matches: Array[RegExMatch] = RegEx.create_from_string("\\|").search_all(rgroup_match.get_string("options")) + for separator_match in separator_matches: + colors[start_index + rgroup_match.get_start("options") + separator_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + rgroup_match.get_start("options") + separator_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + colors[start_index + rgroup_match.get_end("options")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + rgroup_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} + + return colors + + +## Returns the syntax highlighting for an expression (mutation set/do, or condition) +func _get_expression_syntax_highlighting(start_index: int, type: ExpressionType, text: String) -> Dictionary: + var text_edit: TextEdit = get_text_edit() + var colors: Dictionary = {} + + if type == ExpressionType.SET: + var assignment_matches: Array[RegExMatch] = regex_assignment.search_all(text) + for assignment_match in assignment_matches: + colors[start_index + assignment_match.get_start("var")] = {"color": text_edit.theme_overrides.text_color} + if "attr" in assignment_match.names: + colors[start_index + assignment_match.get_start("attr")] = {"color": text_edit.theme_overrides.members_color} + colors[start_index + assignment_match.get_end("attr")] = {"color": text_edit.theme_overrides.text_color} + if "key" in assignment_match.names: + # Braces are outside of the key, so coloring them symbols_color + colors[start_index + assignment_match.get_start("key") - 1] = {"color": text_edit.theme_overrides.symbols_color} + colors.merge(_get_literal_syntax_highlighting(start_index + assignment_match.get_start("key"), assignment_match.get_string("key")), true) + colors[start_index + assignment_match.get_end("key")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + assignment_match.get_end("key") + 1] = {"color": text_edit.theme_overrides.text_color} + + colors[start_index + assignment_match.get_start("op")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + assignment_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + assignment_match.get_start("val"), assignment_match.get_string("val")), true) + else: + colors.merge(_get_literal_syntax_highlighting(start_index, text), true) + + return colors + + +## Returns the syntax highlighting for a literal. +## For this purpose, "literal" refers to a regular code line that could be used to get a value out of: +## - function calls +## - real literals (bool, string, int, float, etc.) +## - logical operators (>, <, >=, or, and, not, etc.) +func _get_literal_syntax_highlighting(start_index: int, text: String) -> Dictionary: + var text_edit: TextEdit = get_text_edit() + var colors: Dictionary = {} + + # Removing spaces at start/end of the literal + var text_length: int = text.length() + text = text.lstrip(" ") + start_index += text_length - text.length() + text = text.rstrip(" ") + + # Parenthesis expression. + var paren_matches: Array[RegExMatch] = regex_paren.search_all(text) + for paren_match in paren_matches: + colors[start_index + paren_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + paren_match.get_start(0) + 1] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + paren_match.get_start("paren"), paren_match.get_string("paren")), true) + colors[start_index + paren_match.get_end(0) - 1] = {"color": text_edit.theme_overrides.symbols_color} + + # Strings. + var string_matches: Array[RegExMatch] = regex_string.search_all(text) + for string_match in string_matches: + colors[start_index + string_match.get_start(0)] = {"color": text_edit.theme_overrides.strings_color} + if "content" in string_match.names: + var escape_matches: Array[RegExMatch] = regex_escape.search_all(string_match.get_string("content")) + for escape_match in escape_matches: + colors[start_index + string_match.get_start("content") + escape_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + string_match.get_start("content") + escape_match.get_end(0)] = {"color": text_edit.theme_overrides.strings_color} + + # Numbers. + var number_matches: Array[RegExMatch] = regex_number.search_all(text) + for number_match in number_matches: + colors[start_index + number_match.get_start(0)] = {"color": text_edit.theme_overrides.numbers_color} + + # Arrays. + var array_matches: Array[RegExMatch] = regex_array.search_all(text) + for array_match in array_matches: + colors[start_index + array_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors.merge(_get_list_syntax_highlighting(start_index + array_match.get_start(1), array_match.strings[1]), true) + colors[start_index + array_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + + # Dictionaries. + var dict_matches: Array[RegExMatch] = regex_dict.search_all(text) + for dict_match in dict_matches: + colors[start_index + dict_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} + colors.merge(_get_list_syntax_highlighting(start_index + dict_match.get_start(1), dict_match.strings[1]), true) + colors[start_index + dict_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + + # Dictionary key: value pairs + var kvdict_matches: Array[RegExMatch] = regex_kvdict.search_all(text) + for kvdict_match in kvdict_matches: + colors.merge(_get_literal_syntax_highlighting(start_index + kvdict_match.get_start("left"), kvdict_match.get_string("left")), true) + colors[start_index + kvdict_match.get_start("colon")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + kvdict_match.get_end("colon")] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + kvdict_match.get_start("right"), kvdict_match.get_string("right")), true) + + # Booleans. + var bool_matches: Array[RegExMatch] = regex_keyword.search_all(text) + for bool_match in bool_matches: + colors[start_index + bool_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} + + # Functions. + var function_matches: Array[RegExMatch] = regex_function.search_all(text) + for function_match in function_matches: + var last_brace_index: int = text.rfind(")") + colors[start_index + function_match.get_start(1)] = {"color": text_edit.theme_overrides.mutations_color} + colors[start_index + function_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} + colors.merge(_get_list_syntax_highlighting(start_index + function_match.get_end(0), text.substr(function_match.get_end(0), last_brace_index - function_match.get_end(0))), true) + colors[start_index + last_brace_index] = {"color": text_edit.theme_overrides.symbols_color} + + # Variables. + var varname_matches: Array[RegExMatch] = regex_varname.search_all(text) + for varname_match in varname_matches: + colors[start_index + varname_match.get_start("var")] = {"color": text_edit.theme_overrides.text_color} + if "attr" in varname_match.names: + colors[start_index + varname_match.get_start("attr")] = {"color": text_edit.theme_overrides.members_color} + colors[start_index + varname_match.get_end("attr")] = {"color": text_edit.theme_overrides.text_color} + if "key" in varname_match.names: + # Braces are outside of the key, so coloring them symbols_color + colors[start_index + varname_match.get_start("key") - 1] = {"color": text_edit.theme_overrides.symbols_color} + colors.merge(_get_literal_syntax_highlighting(start_index + varname_match.get_start("key"), varname_match.get_string("key")), true) + colors[start_index + varname_match.get_end("key")] = {"color": text_edit.theme_overrides.symbols_color} + + # Comparison operators. + var comparison_matches: Array[RegExMatch] = regex_comparison.search_all(text) + for comparison_match in comparison_matches: + colors.merge(_get_literal_syntax_highlighting(start_index + comparison_match.get_start("left"), comparison_match.get_string("left")), true) + colors[start_index + comparison_match.get_start("op")] = {"color": text_edit.theme_overrides.symbols_color} + colors[start_index + comparison_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} + var right = comparison_match.get_string("right") + if right.ends_with(":"): + right = right.substr(0, right.length() - 1) + colors.merge(_get_literal_syntax_highlighting(start_index + comparison_match.get_start("right"), right), true) + colors[start_index + comparison_match.get_start("right") + right.length()] = { "color": text_edit.theme_overrides.symbols_color } + + # Logical binary operators. + var blogical_matches: Array[RegExMatch] = regex_blogical.search_all(text) + for blogical_match in blogical_matches: + colors.merge(_get_literal_syntax_highlighting(start_index + blogical_match.get_start("left"), blogical_match.get_string("left")), true) + colors[start_index + blogical_match.get_start("op")] = {"color": text_edit.theme_overrides.conditions_color} + colors[start_index + blogical_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + blogical_match.get_start("right"), blogical_match.get_string("right")), true) + + # Logical unary operators. + var ulogical_matches: Array[RegExMatch] = regex_ulogical.search_all(text) + for ulogical_match in ulogical_matches: + colors[start_index + ulogical_match.get_start("op")] = {"color": text_edit.theme_overrides.conditions_color} + colors[start_index + ulogical_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} + colors.merge(_get_literal_syntax_highlighting(start_index + ulogical_match.get_start("right"), ulogical_match.get_string("right")), true) + + return colors + + +## Returns the syntax coloring for a list of literals separated by commas +func _get_list_syntax_highlighting(start_index: int, text: String) -> Dictionary: + var text_edit: TextEdit = get_text_edit() + var colors: Dictionary = {} + + # Comma-separated list of literals (for arrays and function arguments) + var element_matches: Array[RegExMatch] = regex_commas.search_all(text) + for element_match in element_matches: + colors.merge(_get_literal_syntax_highlighting(start_index + element_match.get_start(1), element_match.strings[1]), true) + + return colors diff --git a/addons/dialogue_manager/components/dialogue_cache.gd b/addons/dialogue_manager/components/dialogue_cache.gd new file mode 100644 index 0000000..5304d4b --- /dev/null +++ b/addons/dialogue_manager/components/dialogue_cache.gd @@ -0,0 +1,160 @@ +extends Node + + +const DialogueConstants = preload("../constants.gd") +const DialogueSettings = preload("../settings.gd") +const DialogueManagerParseResult = preload("./parse_result.gd") + + +# Keeps track of errors and dependencies. +# { +# <dialogue file path> = { +# path = <dialogue file path>, +# dependencies = [<dialogue file path>, <dialogue file path>], +# errors = [<error>, <error>] +# } +# } +var _cache: Dictionary = {} + +var _update_dependency_timer: Timer = Timer.new() +var _update_dependency_paths: PackedStringArray = [] + + +func _ready() -> void: + add_child(_update_dependency_timer) + _update_dependency_timer.timeout.connect(_on_update_dependency_timeout) + + _build_cache() + + +func reimport_files(files: PackedStringArray = []) -> void: + if files.is_empty(): files = get_files() + + var file_system: EditorFileSystem = Engine.get_meta("DialogueManagerPlugin") \ + .get_editor_interface() \ + .get_resource_filesystem() + + # NOTE: Godot 4.2rc1 has an issue with reimporting more than one + # file at a time so we do them one by one + for file in files: + file_system.reimport_files([file]) + await get_tree().create_timer(0.2) + + +## Add a dialogue file to the cache. +func add_file(path: String, parse_results: DialogueManagerParseResult = null) -> void: + _cache[path] = { + path = path, + dependencies = [], + errors = [] + } + + if parse_results != null: + _cache[path].dependencies = Array(parse_results.imported_paths).filter(func(d): return d != path) + _cache[path].parsed_at = Time.get_ticks_msec() + + # If this is a fresh cache entry then we need to check for dependencies + if parse_results == null and not _update_dependency_paths.has(path): + queue_updating_dependencies(path) + + +## Get the file paths in the cache. +func get_files() -> PackedStringArray: + return _cache.keys() + + +## Remember any errors in a dialogue file. +func add_errors_to_file(path: String, errors: Array[Dictionary]) -> void: + if _cache.has(path): + _cache[path].errors = errors + else: + _cache[path] = { + path = path, + resource_path = "", + dependencies = [], + errors = errors + } + + +## Get a list of files that have errors in them. +func get_files_with_errors() -> Array[Dictionary]: + var files_with_errors: Array[Dictionary] = [] + for dialogue_file in _cache.values(): + if dialogue_file and dialogue_file.errors.size() > 0: + files_with_errors.append(dialogue_file) + return files_with_errors + + +## Queue a file to have it's dependencies checked +func queue_updating_dependencies(of_path: String) -> void: + _update_dependency_timer.stop() + if not _update_dependency_paths.has(of_path): + _update_dependency_paths.append(of_path) + _update_dependency_timer.start(0.5) + + +## Update any references to a file path that has moved +func move_file_path(from_path: String, to_path: String) -> void: + if not _cache.has(from_path): return + + if to_path != "": + _cache[to_path] = _cache[from_path].duplicate() + _cache.erase(from_path) + + +## Get any dialogue files that import a given path. +func get_files_with_dependency(imported_path: String) -> Array: + return _cache.values().filter(func(d): return d.dependencies.has(imported_path)) + + +## Get any paths that are dependent on a given path +func get_dependent_paths_for_reimport(on_path: String) -> PackedStringArray: + return get_files_with_dependency(on_path) \ + .filter(func(d): return Time.get_ticks_msec() - d.get("parsed_at", 0) > 3000) \ + .map(func(d): return d.path) + + +# Build the initial cache for dialogue files. +func _build_cache() -> void: + var current_files: PackedStringArray = _get_dialogue_files_in_filesystem() + for file in current_files: + add_file(file) + + +# Recursively find any dialogue files in a directory +func _get_dialogue_files_in_filesystem(path: String = "res://") -> PackedStringArray: + var files: PackedStringArray = [] + + if DirAccess.dir_exists_absolute(path): + var dir = DirAccess.open(path) + dir.list_dir_begin() + var file_name = dir.get_next() + while file_name != "": + var file_path: String = (path + "/" + file_name).simplify_path() + if dir.current_is_dir(): + if not file_name in [".godot", ".tmp"]: + files.append_array(_get_dialogue_files_in_filesystem(file_path)) + elif file_name.get_extension() == "dialogue": + files.append(file_path) + file_name = dir.get_next() + + return files + + +### Signals + + +func _on_update_dependency_timeout() -> void: + _update_dependency_timer.stop() + var import_regex: RegEx = RegEx.create_from_string("import \"(?<path>.*?)\"") + var file: FileAccess + var found_imports: Array[RegExMatch] + for path in _update_dependency_paths: + # Open the file and check for any "import" lines + file = FileAccess.open(path, FileAccess.READ) + found_imports = import_regex.search_all(file.get_as_text()) + var dependencies: PackedStringArray = [] + for found in found_imports: + dependencies.append(found.strings[found.names.path]) + _cache[path].dependencies = dependencies + _update_dependency_paths.clear() diff --git a/addons/dialogue_manager/components/download_update_panel.gd b/addons/dialogue_manager/components/download_update_panel.gd new file mode 100644 index 0000000..617d308 --- /dev/null +++ b/addons/dialogue_manager/components/download_update_panel.gd @@ -0,0 +1,84 @@ +@tool +extends Control + + +signal failed() +signal updated(updated_to_version: String) + + +const DialogueConstants = preload("../constants.gd") + +const TEMP_FILE_NAME = "user://temp.zip" + + +@onready var logo: TextureRect = %Logo +@onready var label: Label = $VBox/Label +@onready var http_request: HTTPRequest = $HTTPRequest +@onready var download_button: Button = %DownloadButton + +var next_version_release: Dictionary: + set(value): + next_version_release = value + label.text = DialogueConstants.translate(&"update.is_available_for_download") % value.tag_name.substr(1) + get: + return next_version_release + + +func _ready() -> void: + $VBox/Center/DownloadButton.text = DialogueConstants.translate(&"update.download_update") + $VBox/Center2/NotesButton.text = DialogueConstants.translate(&"update.release_notes") + + +### Signals + + +func _on_download_button_pressed() -> void: + # Safeguard the actual dialogue manager repo from accidentally updating itself + if FileAccess.file_exists("res://examples/test_scenes/test_scene.gd"): + prints("You can't update the addon from within itself.") + failed.emit() + return + + http_request.request(next_version_release.zipball_url) + download_button.disabled = true + download_button.text = DialogueConstants.translate(&"update.downloading") + + +func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void: + if result != HTTPRequest.RESULT_SUCCESS: + failed.emit() + return + + # Save the downloaded zip + var zip_file: FileAccess = FileAccess.open(TEMP_FILE_NAME, FileAccess.WRITE) + zip_file.store_buffer(body) + zip_file.close() + + OS.move_to_trash(ProjectSettings.globalize_path("res://addons/dialogue_manager")) + + var zip_reader: ZIPReader = ZIPReader.new() + zip_reader.open(TEMP_FILE_NAME) + var files: PackedStringArray = zip_reader.get_files() + + var base_path = files[1] + # Remove archive folder + files.remove_at(0) + # Remove assets folder + files.remove_at(0) + + for path in files: + var new_file_path: String = path.replace(base_path, "") + if path.ends_with("/"): + DirAccess.make_dir_recursive_absolute("res://addons/%s" % new_file_path) + else: + var file: FileAccess = FileAccess.open("res://addons/%s" % new_file_path, FileAccess.WRITE) + file.store_buffer(zip_reader.read_file(path)) + + zip_reader.close() + DirAccess.remove_absolute(TEMP_FILE_NAME) + + updated.emit(next_version_release.tag_name.substr(1)) + + +func _on_notes_button_pressed() -> void: + OS.shell_open(next_version_release.html_url) diff --git a/addons/dialogue_manager/components/download_update_panel.tscn b/addons/dialogue_manager/components/download_update_panel.tscn new file mode 100644 index 0000000..f3f4523 --- /dev/null +++ b/addons/dialogue_manager/components/download_update_panel.tscn @@ -0,0 +1,60 @@ +[gd_scene load_steps=3 format=3 uid="uid://qdxrxv3c3hxk"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/download_update_panel.gd" id="1_4tm1k"] +[ext_resource type="Texture2D" uid="uid://d3baj6rygkb3f" path="res://addons/dialogue_manager/assets/update.svg" id="2_4o2m6"] + +[node name="DownloadUpdatePanel" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_4tm1k") + +[node name="HTTPRequest" type="HTTPRequest" parent="."] + +[node name="VBox" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -1.0 +offset_top = 9.0 +offset_right = -1.0 +offset_bottom = 9.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/separation = 10 + +[node name="Logo" type="TextureRect" parent="VBox"] +unique_name_in_owner = true +clip_contents = true +custom_minimum_size = Vector2(300, 80) +layout_mode = 2 +texture = ExtResource("2_4o2m6") +stretch_mode = 5 + +[node name="Label" type="Label" parent="VBox"] +layout_mode = 2 +text = "v1.2.3 is available for download." +horizontal_alignment = 1 + +[node name="Center" type="CenterContainer" parent="VBox"] +layout_mode = 2 + +[node name="DownloadButton" type="Button" parent="VBox/Center"] +unique_name_in_owner = true +layout_mode = 2 +text = "Download update" + +[node name="Center2" type="CenterContainer" parent="VBox"] +layout_mode = 2 + +[node name="NotesButton" type="LinkButton" parent="VBox/Center2"] +layout_mode = 2 +text = "Read release notes" + +[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_request_completed"] +[connection signal="pressed" from="VBox/Center/DownloadButton" to="." method="_on_download_button_pressed"] +[connection signal="pressed" from="VBox/Center2/NotesButton" to="." method="_on_notes_button_pressed"] diff --git a/addons/dialogue_manager/components/errors_panel.gd b/addons/dialogue_manager/components/errors_panel.gd new file mode 100644 index 0000000..f3e294d --- /dev/null +++ b/addons/dialogue_manager/components/errors_panel.gd @@ -0,0 +1,85 @@ +@tool +extends HBoxContainer + + +signal error_pressed(line_number) + + +const DialogueConstants = preload("../constants.gd") + + +@onready var error_button: Button = $ErrorButton +@onready var next_button: Button = $NextButton +@onready var count_label: Label = $CountLabel +@onready var previous_button: Button = $PreviousButton + +## The index of the current error being shown +var error_index: int = 0: + set(next_error_index): + error_index = wrap(next_error_index, 0, errors.size()) + show_error() + get: + return error_index + +## The list of all errors +var errors: Array = []: + set(next_errors): + errors = next_errors + self.error_index = 0 + get: + return errors + + +func _ready() -> void: + apply_theme() + hide() + + +## Set up colors and icons +func apply_theme() -> void: + error_button.add_theme_color_override("font_color", get_theme_color("error_color", "Editor")) + error_button.add_theme_color_override("font_hover_color", get_theme_color("error_color", "Editor")) + error_button.icon = get_theme_icon("StatusError", "EditorIcons") + previous_button.icon = get_theme_icon("ArrowLeft", "EditorIcons") + next_button.icon = get_theme_icon("ArrowRight", "EditorIcons") + + +## Move the error index to match a given line +func show_error_for_line_number(line_number: int) -> void: + for i in range(0, errors.size()): + if errors[i].line_number == line_number: + self.error_index = i + + +## Show the current error +func show_error() -> void: + if errors.size() == 0: + hide() + else: + show() + count_label.text = DialogueConstants.translate(&"n_of_n").format({ index = error_index + 1, total = errors.size() }) + var error = errors[error_index] + error_button.text = DialogueConstants.translate(&"errors.line_and_message").format({ line = error.line_number + 1, column = error.column_number, message = DialogueConstants.get_error_message(error.error) }) + if error.has("external_error"): + error_button.text += " " + DialogueConstants.get_error_message(error.external_error) + + +### Signals + + +func _on_errors_panel_theme_changed() -> void: + apply_theme() + + +func _on_error_button_pressed() -> void: + emit_signal("error_pressed", errors[error_index].line_number, errors[error_index].column_number) + + +func _on_previous_button_pressed() -> void: + self.error_index -= 1 + _on_error_button_pressed() + + +func _on_next_button_pressed() -> void: + self.error_index += 1 + _on_error_button_pressed() diff --git a/addons/dialogue_manager/components/errors_panel.tscn b/addons/dialogue_manager/components/errors_panel.tscn new file mode 100644 index 0000000..956552b --- /dev/null +++ b/addons/dialogue_manager/components/errors_panel.tscn @@ -0,0 +1,56 @@ +[gd_scene load_steps=4 format=3 uid="uid://cs8pwrxr5vxix"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/errors_panel.gd" id="1_nfm3c"] + +[sub_resource type="Image" id="Image_wy5pj"] +data = { +"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), +"format": "RGBA8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id="ImageTexture_s6fxl"] +image = SubResource("Image_wy5pj") + +[node name="ErrorsPanel" type="HBoxContainer"] +visible = false +offset_right = 1024.0 +offset_bottom = 600.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_nfm3c") +metadata/_edit_layout_mode = 1 + +[node name="ErrorButton" type="Button" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_color = Color(0, 0, 0, 1) +theme_override_constants/h_separation = 3 +icon = SubResource("ImageTexture_s6fxl") +flat = true +alignment = 0 +text_overrun_behavior = 4 + +[node name="Spacer" type="Control" parent="."] +custom_minimum_size = Vector2(40, 0) +layout_mode = 2 + +[node name="PreviousButton" type="Button" parent="."] +layout_mode = 2 +icon = SubResource("ImageTexture_s6fxl") +flat = true + +[node name="CountLabel" type="Label" parent="."] +layout_mode = 2 + +[node name="NextButton" type="Button" parent="."] +layout_mode = 2 +icon = SubResource("ImageTexture_s6fxl") +flat = true + +[connection signal="pressed" from="ErrorButton" to="." method="_on_error_button_pressed"] +[connection signal="pressed" from="PreviousButton" to="." method="_on_previous_button_pressed"] +[connection signal="pressed" from="NextButton" to="." method="_on_next_button_pressed"] diff --git a/addons/dialogue_manager/components/files_list.gd b/addons/dialogue_manager/components/files_list.gd new file mode 100644 index 0000000..ac4793d --- /dev/null +++ b/addons/dialogue_manager/components/files_list.gd @@ -0,0 +1,144 @@ +@tool +extends VBoxContainer + + +signal file_selected(file_path: String) +signal file_popup_menu_requested(at_position: Vector2) +signal file_double_clicked(file_path: String) +signal file_middle_clicked(file_path: String) + + +const DialogueConstants = preload("../constants.gd") + +const MODIFIED_SUFFIX = "(*)" + + +@export var icon: Texture2D + +@onready var filter_edit: LineEdit = $FilterEdit +@onready var list: ItemList = $List + +var file_map: Dictionary = {} + +var current_file_path: String = "" + +var files: PackedStringArray = []: + set(next_files): + files = next_files + files.sort() + update_file_map() + apply_filter() + get: + return files + +var unsaved_files: Array[String] = [] + +var filter: String: + set(next_filter): + filter = next_filter + apply_filter() + get: + return filter + + +func _ready() -> void: + apply_theme() + + filter_edit.placeholder_text = DialogueConstants.translate(&"files_list.filter") + + +func select_file(file: String) -> void: + list.deselect_all() + for i in range(0, list.get_item_count()): + var item_text = list.get_item_text(i).replace(MODIFIED_SUFFIX, "") + if item_text == get_nice_file(file, item_text.count("/") + 1): + list.select(i) + + +func mark_file_as_unsaved(file: String, is_unsaved: bool) -> void: + if not file in unsaved_files and is_unsaved: + unsaved_files.append(file) + elif file in unsaved_files and not is_unsaved: + unsaved_files.erase(file) + apply_filter() + + +func update_file_map() -> void: + file_map = {} + for file in files: + var nice_file: String = get_nice_file(file) + + # See if a value with just the file name is already in the map + for key in file_map.keys(): + if file_map[key] == nice_file: + var bit_count = nice_file.count("/") + 2 + + var existing_nice_file = get_nice_file(key, bit_count) + nice_file = get_nice_file(file, bit_count) + + while nice_file == existing_nice_file: + bit_count += 1 + existing_nice_file = get_nice_file(key, bit_count) + nice_file = get_nice_file(file, bit_count) + + file_map[key] = existing_nice_file + + file_map[file] = nice_file + + +func get_nice_file(file_path: String, path_bit_count: int = 1) -> String: + var bits = file_path.replace("res://", "").replace(".dialogue", "").split("/") + bits = bits.slice(-path_bit_count) + return "/".join(bits) + + +func apply_filter() -> void: + list.clear() + for file in file_map.keys(): + if filter == "" or filter.to_lower() in file.to_lower(): + var nice_file = file_map[file] + if file in unsaved_files: + nice_file += MODIFIED_SUFFIX + var new_id := list.add_item(nice_file) + list.set_item_icon(new_id, icon) + + select_file(current_file_path) + + +func apply_theme() -> void: + if is_instance_valid(filter_edit): + filter_edit.right_icon = get_theme_icon("Search", "EditorIcons") + + +### Signals + + +func _on_theme_changed() -> void: + apply_theme() + + +func _on_filter_edit_text_changed(new_text: String) -> void: + self.filter = new_text + + +func _on_list_item_clicked(index: int, at_position: Vector2, mouse_button_index: int) -> void: + if mouse_button_index == MOUSE_BUTTON_LEFT: + var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") + var file = file_map.find_key(item_text) + select_file(file) + file_selected.emit(file) + + if mouse_button_index == MOUSE_BUTTON_RIGHT: + file_popup_menu_requested.emit(at_position) + + if mouse_button_index == MOUSE_BUTTON_MIDDLE: + var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") + var file = file_map.find_key(item_text) + file_middle_clicked.emit(file) + + +func _on_list_item_activated(index: int) -> void: + var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") + var file = file_map.find_key(item_text) + select_file(file) + file_double_clicked.emit(file) diff --git a/addons/dialogue_manager/components/files_list.tscn b/addons/dialogue_manager/components/files_list.tscn new file mode 100644 index 0000000..12bee0b --- /dev/null +++ b/addons/dialogue_manager/components/files_list.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=5 format=3 uid="uid://dnufpcdrreva3"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/files_list.gd" id="1_cytii"] +[ext_resource type="Texture2D" uid="uid://d3lr2uas6ax8v" path="res://addons/dialogue_manager/assets/icon.svg" id="2_3ijx1"] + +[sub_resource type="Image" id="Image_h3jns"] +data = { +"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), +"format": "RGBA8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id="ImageTexture_44sbr"] +image = SubResource("Image_h3jns") + +[node name="FilesList" type="VBoxContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_cytii") +icon = ExtResource("2_3ijx1") + +[node name="FilterEdit" type="LineEdit" parent="."] +layout_mode = 2 +placeholder_text = "Filter files" +clear_button_enabled = true +right_icon = SubResource("ImageTexture_44sbr") + +[node name="List" type="ItemList" parent="."] +layout_mode = 2 +size_flags_vertical = 3 + +[connection signal="theme_changed" from="." to="." method="_on_theme_changed"] +[connection signal="text_changed" from="FilterEdit" to="." method="_on_filter_edit_text_changed"] +[connection signal="item_activated" from="List" to="." method="_on_list_item_activated"] +[connection signal="item_clicked" from="List" to="." method="_on_list_item_clicked"] diff --git a/addons/dialogue_manager/components/find_in_files.gd b/addons/dialogue_manager/components/find_in_files.gd new file mode 100644 index 0000000..916b744 --- /dev/null +++ b/addons/dialogue_manager/components/find_in_files.gd @@ -0,0 +1,229 @@ +@tool +extends Control + +signal result_selected(path: String, cursor: Vector2, length: int) + + +const DialogueConstants = preload("../constants.gd") + + +@export var main_view: Control +@export var code_edit: CodeEdit + +@onready var input: LineEdit = %Input +@onready var search_button: Button = %SearchButton +@onready var match_case_button: CheckBox = %MatchCaseButton +@onready var replace_toggle: CheckButton = %ReplaceToggle +@onready var replace_container: VBoxContainer = %ReplaceContainer +@onready var replace_input: LineEdit = %ReplaceInput +@onready var replace_selected_button: Button = %ReplaceSelectedButton +@onready var replace_all_button: Button = %ReplaceAllButton +@onready var results_container: VBoxContainer = %ResultsContainer +@onready var result_template: HBoxContainer = %ResultTemplate + +var current_results: Dictionary = {}: + set(value): + current_results = value + update_results_view() + if current_results.size() == 0: + replace_selected_button.disabled = true + replace_all_button.disabled = true + else: + replace_selected_button.disabled = false + replace_all_button.disabled = false + get: + return current_results + +var selections: PackedStringArray = [] + + +func prepare() -> void: + input.grab_focus() + + var template_label = result_template.get_node("Label") + template_label.get_theme_stylebox(&"focus").bg_color = code_edit.theme_overrides.current_line_color + template_label.add_theme_font_override(&"normal_font", code_edit.get_theme_font(&"font")) + + replace_toggle.set_pressed_no_signal(false) + replace_container.hide() + + $VBoxContainer/HBoxContainer/FindContainer/Label.text = DialogueConstants.translate(&"search.find") + input.placeholder_text = DialogueConstants.translate(&"search.placeholder") + input.text = "" + search_button.text = DialogueConstants.translate(&"search.find_all") + match_case_button.text = DialogueConstants.translate(&"search.match_case") + replace_toggle.text = DialogueConstants.translate(&"search.toggle_replace") + $VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceLabel.text = DialogueConstants.translate(&"search.replace_with") + replace_input.placeholder_text = DialogueConstants.translate(&"search.replace_placeholder") + replace_input.text = "" + replace_all_button.text = DialogueConstants.translate(&"search.replace_all") + replace_selected_button.text = DialogueConstants.translate(&"search.replace_selected") + + selections.clear() + self.current_results = {} + +#region helpers + + +func update_results_view() -> void: + for child in results_container.get_children(): + child.queue_free() + + for path in current_results.keys(): + var path_label: Label = Label.new() + path_label.text = path + # Show open files + if main_view.open_buffers.has(path): + path_label.text += "(*)" + results_container.add_child(path_label) + for path_result in current_results.get(path): + var result_item: HBoxContainer = result_template.duplicate() + + var checkbox: CheckBox = result_item.get_node("CheckBox") as CheckBox + var key: String = get_selection_key(path, path_result) + checkbox.toggled.connect(func(is_pressed): + if is_pressed: + if not selections.has(key): + selections.append(key) + else: + if selections.has(key): + selections.remove_at(selections.find(key)) + ) + checkbox.set_pressed_no_signal(selections.has(key)) + checkbox.visible = replace_toggle.button_pressed + + var result_label: RichTextLabel = result_item.get_node("Label") as RichTextLabel + var colors: Dictionary = code_edit.theme_overrides + var highlight: String = "" + if replace_toggle.button_pressed: + var matched_word: String = "[bgcolor=" + colors.critical_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + path_result.matched_text + "[/color][/bgcolor]" + highlight = "[s]" + matched_word + "[/s][bgcolor=" + colors.notice_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + replace_input.text + "[/color][/bgcolor]" + else: + highlight = "[bgcolor=" + colors.symbols_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + path_result.matched_text + "[/color][/bgcolor]" + var text: String = path_result.text.substr(0, path_result.index) + highlight + path_result.text.substr(path_result.index + path_result.query.length()) + result_label.text = "%s: %s" % [str(path_result.line).lpad(4), text] + result_label.gui_input.connect(func(event): + if event is InputEventMouseButton and (event as InputEventMouseButton).button_index == MOUSE_BUTTON_LEFT and (event as InputEventMouseButton).double_click: + result_selected.emit(path, Vector2(path_result.index, path_result.line), path_result.query.length()) + ) + + results_container.add_child(result_item) + + +func find_in_files() -> Dictionary: + var results: Dictionary = {} + + var q: String = input.text + var cache = Engine.get_meta("DialogueCache") + var file: FileAccess + for path in cache.get_files(): + var path_results: Array = [] + var lines: PackedStringArray = [] + + if main_view.open_buffers.has(path): + lines = main_view.open_buffers.get(path).text.split("\n") + else: + file = FileAccess.open(path, FileAccess.READ) + lines = file.get_as_text().split("\n") + + for i in range(0, lines.size()): + var index: int = find_in_line(lines[i], q) + while index > -1: + path_results.append({ + line = i, + index = index, + text = lines[i], + matched_text = lines[i].substr(index, q.length()), + query = q + }) + index = find_in_line(lines[i], q, index + q.length()) + + if file != null and file.is_open(): + file.close() + + if path_results.size() > 0: + results[path] = path_results + + return results + + +func get_selection_key(path: String, path_result: Dictionary) -> String: + return "%s-%d-%d" % [path, path_result.line, path_result.index] + + +func find_in_line(line: String, query: String, from_index: int = 0) -> int: + if match_case_button.button_pressed: + return line.find(query, from_index) + else: + return line.findn(query, from_index) + + +func replace_results(only_selected: bool) -> void: + var file: FileAccess + var lines: PackedStringArray = [] + for path in current_results: + if main_view.open_buffers.has(path): + lines = main_view.open_buffers.get(path).text.split("\n") + else: + file = FileAccess.open(path, FileAccess.READ_WRITE) + lines = file.get_as_text().split("\n") + + # Read the results in reverse because we're going to be modifying them as we go + var path_results: Array = current_results.get(path).duplicate() + path_results.reverse() + for path_result in path_results: + var key: String = get_selection_key(path, path_result) + if not only_selected or (only_selected and selections.has(key)): + lines[path_result.line] = lines[path_result.line].substr(0, path_result.index) + replace_input.text + lines[path_result.line].substr(path_result.index + path_result.matched_text.length()) + + var replaced_text: String = "\n".join(lines) + if file != null and file.is_open(): + file.seek(0) + file.store_string(replaced_text) + file.close() + else: + main_view.open_buffers.get(path).text = replaced_text + if main_view.current_file_path == path: + code_edit.text = replaced_text + + current_results = find_in_files() + + +#endregion + +#region signals + + +func _on_search_button_pressed() -> void: + selections.clear() + self.current_results = find_in_files() + + +func _on_input_text_submitted(new_text: String) -> void: + _on_search_button_pressed() + + +func _on_replace_toggle_toggled(toggled_on: bool) -> void: + replace_container.visible = toggled_on + if toggled_on: + replace_input.grab_focus() + update_results_view() + + +func _on_replace_input_text_changed(new_text: String) -> void: + update_results_view() + + +func _on_replace_selected_button_pressed() -> void: + replace_results(true) + + +func _on_replace_all_button_pressed() -> void: + replace_results(false) + + +func _on_match_case_button_toggled(toggled_on: bool) -> void: + _on_search_button_pressed() + + +#endregion diff --git a/addons/dialogue_manager/components/find_in_files.tscn b/addons/dialogue_manager/components/find_in_files.tscn new file mode 100644 index 0000000..8aaef4b --- /dev/null +++ b/addons/dialogue_manager/components/find_in_files.tscn @@ -0,0 +1,139 @@ +[gd_scene load_steps=3 format=3 uid="uid://0n7hwviyyly4"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/find_in_files.gd" id="1_3xicy"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_owohg"] +bg_color = Color(0.266667, 0.278431, 0.352941, 0.243137) +corner_detail = 1 + +[node name="FindInFiles" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("1_3xicy") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="FindContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/FindContainer"] +layout_mode = 2 +text = "Find:" + +[node name="Input" type="LineEdit" parent="VBoxContainer/HBoxContainer/FindContainer"] +unique_name_in_owner = true +layout_mode = 2 +clear_button_enabled = true + +[node name="FindToolbar" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/FindContainer"] +layout_mode = 2 + +[node name="SearchButton" type="Button" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Find all..." + +[node name="MatchCaseButton" type="CheckBox" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Match case" + +[node name="Control" type="Control" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ReplaceToggle" type="CheckButton" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Replace" + +[node name="ReplaceContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ReplaceLabel" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] +layout_mode = 2 +text = "Replace with:" + +[node name="ReplaceInput" type="LineEdit" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +clear_button_enabled = true + +[node name="ReplaceToolbar" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] +layout_mode = 2 + +[node name="ReplaceSelectedButton" type="Button" parent="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Replace selected" + +[node name="ReplaceAllButton" type="Button" parent="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Replace all" + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="ReplaceToolbar" type="HBoxContainer" parent="VBoxContainer/VBoxContainer"] +layout_mode = 2 + +[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +follow_focus = true + +[node name="ResultsContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_constants/separation = 0 + +[node name="ResultTemplate" type="HBoxContainer" parent="."] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 155.0 +offset_top = -74.0 +offset_right = 838.0 +offset_bottom = -51.0 + +[node name="CheckBox" type="CheckBox" parent="ResultTemplate"] +layout_mode = 2 + +[node name="Label" type="RichTextLabel" parent="ResultTemplate"] +layout_mode = 2 +size_flags_horizontal = 3 +focus_mode = 2 +theme_override_styles/focus = SubResource("StyleBoxFlat_owohg") +bbcode_enabled = true +text = "Result" +fit_content = true +scroll_active = false + +[connection signal="text_submitted" from="VBoxContainer/HBoxContainer/FindContainer/Input" to="." method="_on_input_text_submitted"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/SearchButton" to="." method="_on_search_button_pressed"] +[connection signal="toggled" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/MatchCaseButton" to="." method="_on_match_case_button_toggled"] +[connection signal="toggled" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/ReplaceToggle" to="." method="_on_replace_toggle_toggled"] +[connection signal="text_changed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceInput" to="." method="_on_replace_input_text_changed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar/ReplaceSelectedButton" to="." method="_on_replace_selected_button_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar/ReplaceAllButton" to="." method="_on_replace_all_button_pressed"] diff --git a/addons/dialogue_manager/components/parse_result.gd b/addons/dialogue_manager/components/parse_result.gd new file mode 100644 index 0000000..d467cb9 --- /dev/null +++ b/addons/dialogue_manager/components/parse_result.gd @@ -0,0 +1,10 @@ +class_name DialogueManagerParseResult extends RefCounted + +var imported_paths: PackedStringArray = [] +var using_states: PackedStringArray = [] +var titles: Dictionary = {} +var character_names: PackedStringArray = [] +var first_title: String = "" +var lines: Dictionary = {} +var errors: Array[Dictionary] = [] +var raw_text: String = "" diff --git a/addons/dialogue_manager/components/parser.gd b/addons/dialogue_manager/components/parser.gd new file mode 100644 index 0000000..ad6e3ac --- /dev/null +++ b/addons/dialogue_manager/components/parser.gd @@ -0,0 +1,1780 @@ +@tool + +class_name DialogueManagerParser extends Object + + +const DialogueConstants = preload("../constants.gd") +const DialogueSettings = preload("../settings.gd") +const ResolvedLineData = preload("./resolved_line_data.gd") +const ResolvedTagData = preload("./resolved_tag_data.gd") +const DialogueManagerParseResult = preload("./parse_result.gd") + + +var IMPORT_REGEX: RegEx = RegEx.create_from_string("import \"(?<path>[^\"]+)\" as (?<prefix>[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+)") +var USING_REGEX: RegEx = RegEx.create_from_string("using (?<state>.*)") +var VALID_TITLE_REGEX: RegEx = RegEx.create_from_string("^[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+$") +var BEGINS_WITH_NUMBER_REGEX: RegEx = RegEx.create_from_string("^\\d") +var TRANSLATION_REGEX: RegEx = RegEx.create_from_string("\\[ID:(?<tr>.*?)\\]") +var TAGS_REGEX: RegEx = RegEx.create_from_string("\\[#(?<tags>.*?)\\]") +var MUTATION_REGEX: RegEx = RegEx.create_from_string("(?<keyword>do|do!|set) (?<mutation>.*)") +var CONDITION_REGEX: RegEx = RegEx.create_from_string("(if|elif|while|else if) (?<condition>.*)") +var WRAPPED_CONDITION_REGEX: RegEx = RegEx.create_from_string("\\[if (?<condition>.*)\\]") +var REPLACEMENTS_REGEX: RegEx = RegEx.create_from_string("{{(.*?)}}") +var GOTO_REGEX: RegEx = RegEx.create_from_string("=><? (?<jump_to_title>.*)") +var INDENT_REGEX: RegEx = RegEx.create_from_string("^\\t+") +var INLINE_RANDOM_REGEX: RegEx = RegEx.create_from_string("\\[\\[(?<options>.*?)\\]\\]") +var INLINE_CONDITIONALS_REGEX: RegEx = RegEx.create_from_string("\\[if (?<condition>.+?)\\](?<body>.*?)\\[\\/if\\]") + +var TOKEN_DEFINITIONS: Dictionary = { + DialogueConstants.TOKEN_FUNCTION: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*\\("), + DialogueConstants.TOKEN_DICTIONARY_REFERENCE: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*\\["), + DialogueConstants.TOKEN_PARENS_OPEN: RegEx.create_from_string("^\\("), + DialogueConstants.TOKEN_PARENS_CLOSE: RegEx.create_from_string("^\\)"), + DialogueConstants.TOKEN_BRACKET_OPEN: RegEx.create_from_string("^\\["), + DialogueConstants.TOKEN_BRACKET_CLOSE: RegEx.create_from_string("^\\]"), + DialogueConstants.TOKEN_BRACE_OPEN: RegEx.create_from_string("^\\{"), + DialogueConstants.TOKEN_BRACE_CLOSE: RegEx.create_from_string("^\\}"), + DialogueConstants.TOKEN_COLON: RegEx.create_from_string("^:"), + DialogueConstants.TOKEN_COMPARISON: RegEx.create_from_string("^(==|<=|>=|<|>|!=|in )"), + DialogueConstants.TOKEN_ASSIGNMENT: RegEx.create_from_string("^(\\+=|\\-=|\\*=|/=|=)"), + DialogueConstants.TOKEN_NUMBER: RegEx.create_from_string("^\\-?\\d+(\\.\\d+)?"), + DialogueConstants.TOKEN_OPERATOR: RegEx.create_from_string("^(\\+|\\-|\\*|/|%)"), + DialogueConstants.TOKEN_COMMA: RegEx.create_from_string("^,"), + DialogueConstants.TOKEN_DOT: RegEx.create_from_string("^\\."), + DialogueConstants.TOKEN_STRING: RegEx.create_from_string("^(\".*?\"|\'.*?\')"), + DialogueConstants.TOKEN_NOT: RegEx.create_from_string("^(not( |$)|!)"), + DialogueConstants.TOKEN_AND_OR: RegEx.create_from_string("^(and|or)( |$)"), + DialogueConstants.TOKEN_VARIABLE: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*"), + DialogueConstants.TOKEN_COMMENT: RegEx.create_from_string("^#.*"), + DialogueConstants.TOKEN_CONDITION: RegEx.create_from_string("^(if|elif|else)"), + DialogueConstants.TOKEN_BOOL: RegEx.create_from_string("^(true|false)") +} + +var WEIGHTED_RANDOM_SIBLINGS_REGEX: RegEx = RegEx.create_from_string("^\\%(?<weight>[\\d.]+)? ") + +var raw_lines: PackedStringArray = [] +var parent_stack: Array[String] = [] + +var parsed_lines: Dictionary = {} +var imported_paths: PackedStringArray = [] +var using_states: PackedStringArray = [] +var titles: Dictionary = {} +var character_names: PackedStringArray = [] +var first_title: String = "" +var errors: Array[Dictionary] = [] +var raw_text: String = "" + +var _imported_line_map: Dictionary = {} +var _imported_line_count: int = 0 + +var while_loopbacks: Array[String] = [] + + +## Parse some raw dialogue text. Returns a dictionary containing parse results +static func parse_string(string: String, path: String) -> DialogueManagerParseResult: + var parser: DialogueManagerParser = DialogueManagerParser.new() + var error: Error = parser.parse(string, path) + var data: DialogueManagerParseResult = parser.get_data() + parser.free() + + if error == OK: + return data + else: + return null + + +## Extract bbcode and other markers from a string +static func extract_markers_from_string(string: String) -> ResolvedLineData: + var parser: DialogueManagerParser = DialogueManagerParser.new() + var markers: ResolvedLineData = parser.extract_markers(string) + parser.free() + + return markers + + +## Parse some raw dialogue text. Returns a dictionary containing parse results +func parse(text: String, path: String) -> Error: + prepare(text, path) + raw_text = text + + # Parse all of the content + var known_translations = {} + + # Get list of known autoloads + var autoload_names: PackedStringArray = get_autoload_names() + + # Keep track of the last doc comment + var doc_comments: Array[String] = [] + + # Then parse all lines + for id in range(0, raw_lines.size()): + var raw_line: String = raw_lines[id] + + var line: Dictionary = { + id = str(id), + next_id = DialogueConstants.ID_NULL + } + + # Work out if we are inside a conditional or option or if we just + # indented back out of one + var indent_size: int = get_indent(raw_line) + if indent_size < parent_stack.size() and not is_line_empty(raw_line): + for _tab in range(0, parent_stack.size() - indent_size): + parent_stack.pop_back() + + # If we are indented then this line should know about its parent + if parent_stack.size() > 0: + line["parent_id"] = parent_stack.back() + + # Trim any indentation (now that we've calculated it) so we can check + # the begining of each line for its type + raw_line = raw_line.strip_edges(true, false) + + # Grab translations + var translation_key: String = extract_translation(raw_line) + if translation_key != "": + line["translation_key"] = translation_key + raw_line = raw_line.replace("[ID:%s]" % translation_key, "") + + # Check for each kind of line + + # Start shortcuts + if raw_line.begins_with("using "): + var using_match: RegExMatch = USING_REGEX.search(raw_line) + if "state" in using_match.names: + var using_state: String = using_match.strings[using_match.names.state].strip_edges() + if not using_state in autoload_names: + add_error(id, 0, DialogueConstants.ERR_UNKNOWN_USING) + elif not using_state in using_states: + using_states.append(using_state) + continue + + # Response + elif is_response_line(raw_line): + # Add any doc notes + line["notes"] = "\n".join(doc_comments) + doc_comments = [] + + parent_stack.append(str(id)) + line["type"] = DialogueConstants.TYPE_RESPONSE + + # Extract any #tags + var tag_data: ResolvedTagData = extract_tags(raw_line) + line["tags"] = tag_data.tags + raw_line = tag_data.line_without_tags + + if " [if " in raw_line: + line["condition"] = extract_condition(raw_line, true, indent_size) + if " =>" in raw_line: + line["next_id"] = extract_goto(raw_line) + if " =><" in raw_line: + # Because of when the return point needs to be known at runtime we need to split + # this line into two (otherwise the return point would be dependent on the balloon) + var goto_line: Dictionary = { + type = DialogueConstants.TYPE_GOTO, + next_id = extract_goto(raw_line), + next_id_after = find_next_line_after_responses(id), + is_snippet = true + } + parsed_lines[str(id) + ".1"] = goto_line + line["next_id"] = str(id) + ".1" + + # Make sure the added goto line can actually go to somewhere + if goto_line.next_id in [DialogueConstants.ID_ERROR, DialogueConstants.ID_ERROR_INVALID_TITLE, DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY]: + line["next_id"] = goto_line.next_id + + line["character"] = "" + line["character_replacements"] = [] as Array[Dictionary] + line["text"] = extract_response_prompt(raw_line) + + var previous_response_id = find_previous_response_id(id) + if parsed_lines.has(previous_response_id): + var previous_response = parsed_lines[previous_response_id] + # Add this response to the list on the first response so that it is the + # authority on what is in the list of responses + previous_response["responses"] = previous_response["responses"] + PackedStringArray([str(id)]) + else: + # No previous response so this is the first in the list + line["responses"] = PackedStringArray([str(id)]) + + line["next_id_after"] = find_next_line_after_responses(id) + + # If this response has no body then the next id is the next id after + if not line.has("next_id") or line.next_id == DialogueConstants.ID_NULL: + var next_nonempty_line_id = get_next_nonempty_line_id(id) + if next_nonempty_line_id != DialogueConstants.ID_NULL: + if get_indent(raw_lines[next_nonempty_line_id.to_int()]) <= indent_size: + line["next_id"] = line.next_id_after + else: + line["next_id"] = next_nonempty_line_id + + line["text_replacements"] = extract_dialogue_replacements(line.get("text"), indent_size + 2) + for replacement in line.text_replacements: + if replacement.has("error"): + add_error(id, replacement.index, replacement.error) + + # If this response has a character name in it then it will automatically be + # injected as a line of dialogue if the player selects it + var response_text: String = line.text.replace("\\:", "!ESCAPED_COLON!") + if ": " in response_text: + if DialogueSettings.get_setting("create_lines_for_responses_with_characters", true): + var first_child: Dictionary = { + type = DialogueConstants.TYPE_DIALOGUE, + next_id = line.next_id, + next_id_after = line.next_id_after, + text_replacements = line.text_replacements, + tags = line.tags, + translation_key = line.get("translation_key") + } + parse_response_character_and_text(id, response_text, first_child, indent_size, parsed_lines) + line["character"] = first_child.character + line["character_replacements"] = first_child.character_replacements + line["text"] = first_child.text + line["translation_key"] = first_child.translation_key + parsed_lines[str(id) + ".2"] = first_child + line["next_id"] = str(id) + ".2" + else: + parse_response_character_and_text(id, response_text, line, indent_size, parsed_lines) + else: + line["text"] = response_text.replace("!ESCAPED_COLON!", ":") + + # Title + elif is_title_line(raw_line): + line["type"] = DialogueConstants.TYPE_TITLE + if not raw_lines[id].begins_with("~"): + add_error(id, indent_size + 2, DialogueConstants.ERR_NESTED_TITLE) + else: + line["text"] = extract_title(raw_line) + # Titles can't have numbers as the first letter (unless they are external titles which get replaced with hashes) + if id >= _imported_line_count and BEGINS_WITH_NUMBER_REGEX.search(line.text): + add_error(id, 2, DialogueConstants.ERR_TITLE_BEGINS_WITH_NUMBER) + # Only import titles are allowed to have "/" in them + var valid_title = VALID_TITLE_REGEX.search(raw_line.replace("/", "").substr(2).strip_edges()) + if not valid_title: + add_error(id, 2, DialogueConstants.ERR_TITLE_INVALID_CHARACTERS) + + # Condition + elif is_condition_line(raw_line, false): + parent_stack.append(str(id)) + line["type"] = DialogueConstants.TYPE_CONDITION + line["condition"] = extract_condition(raw_line, false, indent_size) + line["next_id_after"] = find_next_line_after_conditions(id) + var next_sibling_id = find_next_condition_sibling(id) + line["next_conditional_id"] = next_sibling_id if is_valid_id(next_sibling_id) else line.next_id_after + + elif is_condition_line(raw_line, true): + parent_stack.append(str(id)) + line["type"] = DialogueConstants.TYPE_CONDITION + line["next_id_after"] = find_next_line_after_conditions(id) + line["next_conditional_id"] = line["next_id_after"] + + elif is_while_condition_line(raw_line): + parent_stack.append(str(id)) + line["type"] = DialogueConstants.TYPE_CONDITION + line["condition"] = extract_condition(raw_line, false, indent_size) + line["next_id_after"] = find_next_line_after_conditions(id) + while_loopbacks.append(find_last_line_within_conditions(id)) + line["next_conditional_id"] = line["next_id_after"] + + # Mutation + elif is_mutation_line(raw_line): + line["type"] = DialogueConstants.TYPE_MUTATION + line["mutation"] = extract_mutation(raw_line) + + # Goto + elif is_goto_line(raw_line): + line["type"] = DialogueConstants.TYPE_GOTO + + if raw_line.begins_with("%"): + apply_weighted_random(id, raw_line, indent_size, line) + + line["next_id"] = extract_goto(raw_line) + if is_goto_snippet_line(raw_line): + line["is_snippet"] = true + line["next_id_after"] = get_line_after_line(id, indent_size, line) + else: + line["is_snippet"] = false + + # Nested dialogue + elif is_nested_dialogue_line(raw_line, parsed_lines, raw_lines, indent_size): + var parent_line: Dictionary = parsed_lines.values().back() + var parent_indent_size: int = get_indent(raw_lines[parent_line.id.to_int()]) + var should_update_translation_key: bool = parent_line.translation_key == parent_line.text + var suffix: String = raw_line.strip_edges(true, false) + if suffix == "": + suffix = " " + parent_line["text"] += "\n" + suffix + parent_line["text_replacements"] = extract_dialogue_replacements(parent_line.text, parent_line.character.length() + 2 + parent_indent_size) + for replacement in parent_line.text_replacements: + if replacement.has("error"): + add_error(id, replacement.index, replacement.error) + + if should_update_translation_key: + parent_line["translation_key"] = parent_line.text + + parent_line["next_id"] = get_line_after_line(id, parent_indent_size, parent_line) + + # Ignore this line when checking for indent errors + remove_error(parent_line.id.to_int(), DialogueConstants.ERR_INVALID_INDENTATION) + + var next_line = raw_lines[parent_line.next_id.to_int()] + if not is_dialogue_line(next_line) and get_indent(next_line) >= indent_size: + add_error(parent_line.next_id.to_int(), indent_size, DialogueConstants.ERR_INVALID_INDENTATION) + + continue + + elif raw_line.strip_edges().begins_with("##"): + doc_comments.append(raw_line.replace("##", "").strip_edges()) + continue + + elif is_line_empty(raw_line) or is_import_line(raw_line): + continue + + # Regular dialogue + else: + # Remove escape character + if raw_line.begins_with("\\using"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\if"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\elif"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\else"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\while"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\-"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\~"): raw_line = raw_line.substr(1) + if raw_line.begins_with("\\=>"): raw_line = raw_line.substr(1) + + # Add any doc notes + line["notes"] = "\n".join(doc_comments) + doc_comments = [] + + # Work out any weighted random siblings + if raw_line.begins_with("%"): + apply_weighted_random(id, raw_line, indent_size, line) + raw_line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_line, "") + + line["type"] = DialogueConstants.TYPE_DIALOGUE + + # Extract any tags before we process the line + var tag_data: ResolvedTagData = extract_tags(raw_line) + line["tags"] = tag_data.tags + raw_line = tag_data.line_without_tags + + var l = raw_line.replace("\\:", "!ESCAPED_COLON!") + if ": " in l: + var bits = Array(l.strip_edges().split(": ")) + line["character"] = bits.pop_front().strip_edges() + if not line["character"] in character_names: + character_names.append(line["character"]) + # You can use variables in the character's name + line["character_replacements"] = extract_dialogue_replacements(line.character, indent_size) + for replacement in line.character_replacements: + if replacement.has("error"): + add_error(id, replacement.index, replacement.error) + line["text"] = ": ".join(bits).replace("!ESCAPED_COLON!", ":") + else: + line["character"] = "" + line["character_replacements"] = [] as Array[Dictionary] + line["text"] = l.replace("!ESCAPED_COLON!", ":") + + line["text_replacements"] = extract_dialogue_replacements(line.text, line.character.length() + 2 + indent_size) + for replacement in line.text_replacements: + if replacement.has("error"): + add_error(id, replacement.index, replacement.error) + + # Unescape any newlines + line["text"] = line.text.replace("\\n", "\n").strip_edges() + + # Work out where to go after this line + if line.next_id == DialogueConstants.ID_NULL: + line["next_id"] = get_line_after_line(id, indent_size, line) + + # Check for duplicate translation keys + if line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: + if line.has("translation_key"): + if known_translations.has(line.translation_key) and known_translations.get(line.translation_key) != line.text: + add_error(id, indent_size, DialogueConstants.ERR_DUPLICATE_ID) + else: + known_translations[line.translation_key] = line.text + else: + # Default translations key + if DialogueSettings.get_setting("missing_translations_are_errors", false): + add_error(id, indent_size, DialogueConstants.ERR_MISSING_ID) + else: + line["translation_key"] = line.text + + ## Error checking + + # Can't find goto + var jump_index: int = raw_line.find("=>") + match line.next_id: + DialogueConstants.ID_ERROR: + add_error(id, jump_index, DialogueConstants.ERR_UNKNOWN_TITLE) + DialogueConstants.ID_ERROR_INVALID_TITLE: + add_error(id, jump_index, DialogueConstants.ERR_INVALID_TITLE_REFERENCE) + DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY: + add_error(id, jump_index, DialogueConstants.ERR_TITLE_REFERENCE_HAS_NO_CONTENT) + + # Line after condition isn't indented once to the right + if line.type == DialogueConstants.TYPE_CONDITION: + if is_valid_id(line.next_id): + var next_line: String = raw_lines[line.next_id.to_int()] + var next_indent: int = get_indent(next_line) + if next_indent != indent_size + 1: + add_error(line.next_id.to_int(), next_indent, DialogueConstants.ERR_INVALID_INDENTATION) + else: + add_error(id, indent_size, DialogueConstants.ERR_INVALID_CONDITION_INDENTATION) + + # Line after normal line is indented to the right + elif line.type in [ + DialogueConstants.TYPE_TITLE, + DialogueConstants.TYPE_DIALOGUE, + DialogueConstants.TYPE_MUTATION, + DialogueConstants.TYPE_GOTO + ] and is_valid_id(line.next_id): + var next_line = raw_lines[line.next_id.to_int()] + if next_line != null and get_indent(next_line) > indent_size: + add_error(id, indent_size, DialogueConstants.ERR_INVALID_INDENTATION) + + # Parsing condition failed + if line.has("condition") and line.condition.has("error"): + add_error(id, line.condition.index, line.condition.error) + + # Parsing mutation failed + elif line.has("mutation") and line.mutation.has("error"): + add_error(id, line.mutation.index, line.mutation.error) + + # Line failed to parse at all + if line.get("type") == DialogueConstants.TYPE_UNKNOWN: + add_error(id, 0, DialogueConstants.ERR_UNKNOWN_LINE_SYNTAX) + + # If there are no titles then use the first actual line + if first_title == "" and not is_import_line(raw_line): + first_title = str(id) + + # If this line is the last line of a while loop, edit the id of its next line + if str(id) in while_loopbacks: + if is_goto_snippet_line(raw_line): + line["next_id_after"] = line["parent_id"] + elif is_condition_line(raw_line, true) or is_while_condition_line(raw_line): + line["next_conditional_id"] = line["parent_id"] + line["next_id_after"] = line["parent_id"] + elif is_goto_line(raw_line) or is_title_line(raw_line): + pass + else: + line["next_id"] = line["parent_id"] + + # Done! + parsed_lines[str(id)] = line + + # Assume the last line ends the dialogue + var last_line: Dictionary = parsed_lines.values()[parsed_lines.values().size() - 1] + if last_line.next_id == "": + last_line.next_id = DialogueConstants.ID_END + + if errors.size() > 0: + return ERR_PARSE_ERROR + + return OK + + +func get_data() -> DialogueManagerParseResult: + var data: DialogueManagerParseResult = DialogueManagerParseResult.new() + data.imported_paths = imported_paths + data.using_states = using_states + data.titles = titles + data.character_names = character_names + data.first_title = first_title + data.lines = parsed_lines + data.errors = errors + data.raw_text = raw_text + return data + + +## Get the last parse errors +func get_errors() -> Array[Dictionary]: + return errors + + +## Prepare the parser by collecting all lines and titles +func prepare(text: String, path: String, include_imported_titles_hashes: bool = true) -> void: + using_states = [] + errors = [] + imported_paths = [] + _imported_line_map = {} + while_loopbacks = [] + titles = {} + character_names = [] + first_title = "" + raw_lines = text.split("\n") + + # Work out imports + var known_imports: Dictionary = {} + + # Include the base file path so that we can get around circular dependencies + known_imports[path.hash()] = "." + + var imported_titles: Dictionary = {} + for id in range(0, raw_lines.size()): + var line = raw_lines[id] + if is_import_line(line): + var import_data = extract_import_path_and_name(line) + var import_hash: int = import_data.path.hash() + if import_data.size() > 0: + # Keep track of titles so we can add imported ones later + if str(import_hash) in imported_titles.keys(): + add_error(id, 0, DialogueConstants.ERR_FILE_ALREADY_IMPORTED) + if import_data.prefix in imported_titles.values(): + add_error(id, 0, DialogueConstants.ERR_DUPLICATE_IMPORT_NAME) + imported_titles[str(import_hash)] = import_data.prefix + + # Import the file content + if not known_imports.has(import_hash): + var error: Error = import_content(import_data.path, import_data.prefix, _imported_line_map, known_imports) + if error != OK: + add_error(id, 0, error) + + # Make a map so we can refer compiled lines to where they were imported from + if not _imported_line_map.has(import_hash): + _imported_line_map[import_hash] = { + hash = import_hash, + imported_on_line_number = id, + from_line = 0, + to_line = 0 + } + + var imported_content: String = "" + var cummulative_line_number: int = 0 + for item in _imported_line_map.values(): + item["from_line"] = cummulative_line_number + if known_imports.has(item.hash): + cummulative_line_number += known_imports[item.hash].split("\n").size() + item["to_line"] = cummulative_line_number + if known_imports.has(item.hash): + imported_content += known_imports[item.hash] + "\n" + + _imported_line_count = cummulative_line_number + 1 + + # Join it with the actual content + raw_lines = (imported_content + "\n" + text).split("\n") + + # Find all titles first + for id in range(0, raw_lines.size()): + if raw_lines[id].begins_with("~ "): + var title: String = extract_title(raw_lines[id]) + if title == "": + add_error(id, 2, DialogueConstants.ERR_EMPTY_TITLE) + elif titles.has(title): + add_error(id, 2, DialogueConstants.ERR_DUPLICATE_TITLE) + else: + var next_nonempty_line_id: String = get_next_nonempty_line_id(id) + if next_nonempty_line_id != DialogueConstants.ID_NULL: + titles[title] = next_nonempty_line_id + if "/" in title: + if include_imported_titles_hashes == false: + titles.erase(title) + var bits: PackedStringArray = title.split("/") + if imported_titles.has(bits[0]): + title = imported_titles[bits[0]] + "/" + bits[1] + titles[title] = next_nonempty_line_id + elif first_title == "": + first_title = next_nonempty_line_id + else: + titles[title] = DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY + + +func add_error(line_number: int, column_number: int, error: int) -> void: + # See if the error was in an imported file + for item in _imported_line_map.values(): + if line_number < item.to_line: + errors.append({ + line_number = item.imported_on_line_number, + column_number = 0, + error = DialogueConstants.ERR_ERRORS_IN_IMPORTED_FILE, + external_error = error, + external_line_number = line_number + }) + return + + # Otherwise, it's in this file + errors.append({ + line_number = line_number - _imported_line_count, + column_number = column_number, + error = error + }) + + +func remove_error(line_number: int, error: int) -> void: + for i in range(errors.size() - 1, -1, -1): + var err = errors[i] + var is_native_error = err.line_number == line_number - _imported_line_count and err.error == error + var is_external_error = err.get("external_line_number") == line_number and err.get("external_error") == error + if is_native_error or is_external_error: + errors.remove_at(i) + return + + +func is_import_line(line: String) -> bool: + return line.begins_with("import ") and " as " in line + + +func is_title_line(line: String) -> bool: + return line.strip_edges(true, false).begins_with("~ ") + + +func is_condition_line(line: String, include_else: bool = true) -> bool: + line = line.strip_edges(true, false) + if line.begins_with("if ") or line.begins_with("elif ") or line.begins_with("else if"): return true + if include_else and line.begins_with("else"): return true + return false + +func is_while_condition_line(line: String) -> bool: + line = line.strip_edges(true, false) + if line.begins_with("while "): return true + return false + + +func is_mutation_line(line: String) -> bool: + line = line.strip_edges(true, false) + return line.begins_with("do ") or line.begins_with("do! ") or line.begins_with("set ") + + +func is_goto_line(line: String) -> bool: + line = line.strip_edges(true, false) + line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(line, "") + return line.begins_with("=> ") or line.begins_with("=>< ") + + +func is_goto_snippet_line(line: String) -> bool: + line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(line.strip_edges(), "") + return line.begins_with("=>< ") + + +func is_nested_dialogue_line(raw_line: String, parsed_lines: Dictionary, raw_lines: PackedStringArray, indent_size: int) -> bool: + if parsed_lines.values().is_empty(): return false + if raw_line.strip_edges().begins_with("#"): return false + + var parent_line: Dictionary = parsed_lines.values().back() + if parent_line.type != DialogueConstants.TYPE_DIALOGUE: return false + if get_indent(raw_lines[parent_line.id.to_int()]) >= indent_size: return false + return true + + +func is_dialogue_line(line: String) -> bool: + if line == null: return false + if is_response_line(line): return false + if is_title_line(line): return false + if is_condition_line(line, true): return false + if is_mutation_line(line): return false + if is_goto_line(line): return false + return true + + +func is_response_line(line: String) -> bool: + return line.strip_edges(true, false).begins_with("- ") + + +func is_valid_id(id: String) -> bool: + return false if id in [DialogueConstants.ID_NULL, DialogueConstants.ID_ERROR, DialogueConstants.ID_END_CONVERSATION] else true + + +func is_line_empty(line: String) -> bool: + line = line.strip_edges() + + if line == "": return true + if line == "endif": return true + if line.begins_with("#"): return true + + return false + + +func get_line_after_line(id: int, indent_size: int, line: Dictionary) -> String: + # Unless the next line is an outdent we can assume it comes next + var next_nonempty_line_id = get_next_nonempty_line_id(id) + if next_nonempty_line_id != DialogueConstants.ID_NULL \ + and indent_size <= get_indent(raw_lines[next_nonempty_line_id.to_int()]): + # The next line is a title so we need the next nonempty line after that + if is_title_line(raw_lines[next_nonempty_line_id.to_int()]): + return get_next_nonempty_line_id(next_nonempty_line_id.to_int()) + # Otherwise it's a normal line + else: + return next_nonempty_line_id + # Otherwise, we grab the ID from the parents next ID after children + elif line.has("parent_id") and parsed_lines.has(line.parent_id): + return parsed_lines[line.parent_id].next_id_after + + else: + return DialogueConstants.ID_NULL + + +func get_indent(line: String) -> int: + var tabs: RegExMatch = INDENT_REGEX.search(line) + if tabs: + return tabs.get_string().length() + else: + return 0 + + +func get_next_nonempty_line_id(line_number: int) -> String: + for i in range(line_number + 1, raw_lines.size()): + if not is_line_empty(raw_lines[i]): + return str(i) + return DialogueConstants.ID_NULL + + +func find_previous_response_id(line_number: int) -> String: + var line = raw_lines[line_number] + var indent_size = get_indent(line) + + # Look back up the list to find the previous response + var last_found_response_id: String = str(line_number) + + for i in range(line_number - 1, -1, -1): + line = raw_lines[i] + + if is_line_empty(line): continue + + # If its a response at the same indent level then its a match + elif get_indent(line) == indent_size: + if line.strip_edges().begins_with("- "): + last_found_response_id = str(i) + else: + return last_found_response_id + + # Return itself if nothing was found + return last_found_response_id + + +func apply_weighted_random(id: int, raw_line: String, indent_size: int, line: Dictionary) -> void: + var weight: float = 1 + var found = WEIGHTED_RANDOM_SIBLINGS_REGEX.search(raw_line) + if found and found.names.has("weight"): + weight = found.strings[found.names.weight].to_float() + + # Look back up the list to find the first weighted random line in this group + var original_random_line: Dictionary = {} + for i in range(id, 0, -1): + # Ignore doc comment lines + if raw_lines[i].strip_edges().begins_with("##"): + continue + # Lines that aren't prefixed with the random token are a dead end + if not raw_lines[i].strip_edges().begins_with("%") or get_indent(raw_lines[i]) != indent_size: + break + # Make sure we group random dialogue and random lines separately + elif WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_line.strip_edges(), "").begins_with("=") != WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_lines[i].strip_edges(), "").begins_with("="): + break + # Otherwise we've found the origin + elif parsed_lines.has(str(i)) and parsed_lines[str(i)].has("siblings"): + original_random_line = parsed_lines[str(i)] + break + + # Attach it to the original random line and work out where to go after the line + if original_random_line.size() > 0: + original_random_line["siblings"] += [{ weight = weight, id = str(id) }] + if original_random_line.type != DialogueConstants.TYPE_GOTO: + # Update the next line for all siblings (not goto lines, though, they manager their + # own next ID) + original_random_line["next_id"] = get_line_after_line(id, indent_size, line) + for sibling in original_random_line["siblings"]: + if sibling.id in parsed_lines: + parsed_lines[sibling.id]["next_id"] = original_random_line["next_id"] + line["next_id"] = original_random_line.next_id + # Or set up this line as the original + else: + line["siblings"] = [{ weight = weight, id = str(id) }] + line["next_id"] = get_line_after_line(id, indent_size, line) + + if line.next_id == DialogueConstants.ID_NULL: + line["next_id"] = DialogueConstants.ID_END + + +func find_next_condition_sibling(line_number: int) -> String: + var line = raw_lines[line_number] + var expected_indent = get_indent(line) + + # Look down the list and find an elif or else at the same indent level + for i in range(line_number + 1, raw_lines.size()): + line = raw_lines[i] + if is_line_empty(line): continue + + var l = line.strip_edges() + if l.begins_with("~ "): + return DialogueConstants.ID_END_CONVERSATION + + elif get_indent(line) < expected_indent: + return DialogueConstants.ID_NULL + + elif get_indent(line) == expected_indent: + # Found an if, which begins a different block + if l.begins_with("if"): + return DialogueConstants.ID_NULL + + # Found what we're looking for + elif (l.begins_with("elif ") or l.begins_with("else")): + return str(i) + + return DialogueConstants.ID_NULL + + +func find_next_line_after_conditions(line_number: int) -> String: + var line = raw_lines[line_number] + var expected_indent = get_indent(line) + + # Look down the list for the first non condition line at the same or less indent level + for i in range(line_number + 1, raw_lines.size()): + line = raw_lines[i] + + if is_line_empty(line): continue + + var line_indent = get_indent(line) + line = line.strip_edges() + + if is_title_line(line): + return get_next_nonempty_line_id(i) + + elif line_indent > expected_indent: + continue + + elif line_indent == expected_indent: + if line.begins_with("elif ") or line.begins_with("else"): + continue + else: + return str(i) + + elif line_indent < expected_indent: + # We have to check the parent of this block + for p in range(line_number - 1, -1, -1): + line = raw_lines[p] + + if is_line_empty(line): continue + + line_indent = get_indent(line) + if line_indent < expected_indent: + return parsed_lines[str(p)].get("next_id_after", DialogueConstants.ID_NULL) + + return DialogueConstants.ID_END_CONVERSATION + +func find_last_line_within_conditions(line_number: int) -> String: + var line = raw_lines[line_number] + var expected_indent = get_indent(line) + + var candidate = DialogueConstants.ID_NULL + + # Look down the list for the last line that has an indent level 1 more than this line + # Ending the search when you find a line the same or less indent level + for i in range(line_number + 1, raw_lines.size()): + line = raw_lines[i] + + if is_line_empty(line): continue + + var line_indent = get_indent(line) + line = line.strip_edges() + + if line_indent > expected_indent + 1: + continue + elif line_indent == (expected_indent + 1): + candidate = i + else: + break + + return str(candidate) + +func find_next_line_after_responses(line_number: int) -> String: + var line = raw_lines[line_number] + var expected_indent = get_indent(line) + + # Find the first line after this one that has a smaller indent that isn't another option + # If we hit the eof then we give up + for i in range(line_number + 1, raw_lines.size()): + line = raw_lines[i] + + if is_line_empty(line): continue + + var indent = get_indent(line) + + line = line.strip_edges() + + # We hit a title so the next line is a new start + if is_title_line(line): + return get_next_nonempty_line_id(i) + + # Another option + elif line.begins_with("- "): + if indent == expected_indent: + # ...at the same level so we continue + continue + elif indent < expected_indent: + # ...outdented so check the previous parent + var previous_parent = parent_stack[parent_stack.size() - 2] + if parsed_lines.has(str(previous_parent)): + return parsed_lines[str(previous_parent)].next_id_after + else: + return DialogueConstants.ID_NULL + + # We're at the end of a conditional so jump back up to see what's after it + elif line.begins_with("elif ") or line.begins_with("else"): + for p in range(line_number - 1, -1, -1): + line = raw_lines[p] + + if is_line_empty(line): continue + + var line_indent = get_indent(line) + if line_indent < expected_indent: + return parsed_lines[str(p)].next_id_after + + # Otherwise check the indent for an outdent + else: + line_number = i + line = raw_lines[line_number] + if get_indent(line) <= expected_indent: + return str(line_number) + + # EOF so must be end of conversation + return DialogueConstants.ID_END_CONVERSATION + + +## Get the names of any autoloads in the project +func get_autoload_names() -> PackedStringArray: + var autoloads: PackedStringArray = [] + + var project = ConfigFile.new() + project.load("res://project.godot") + if project.has_section("autoload"): + return Array(project.get_section_keys("autoload")).filter(func(key): return key != "DialogueManager") + + return autoloads + + +## Import content from another dialogue file or return an ERR +func import_content(path: String, prefix: String, imported_line_map: Dictionary, known_imports: Dictionary) -> Error: + if FileAccess.file_exists(path): + var file = FileAccess.open(path, FileAccess.READ) + var content: PackedStringArray = file.get_as_text().split("\n") + + var imported_titles: Dictionary = {} + + for index in range(0, content.size()): + var line = content[index] + if is_import_line(line): + var import = extract_import_path_and_name(line) + if import.size() > 0: + if not known_imports.has(import.path.hash()): + # Add an empty record into the keys just so we don't end up with cyclic dependencies + known_imports[import.path.hash()] = "" + if import_content(import.path, import.prefix, imported_line_map, known_imports) != OK: + return ERR_LINK_FAILED + + if not imported_line_map.has(import.path.hash()): + # Make a map so we can refer compiled lines to where they were imported from + imported_line_map[import.path.hash()] = { + hash = import.path.hash(), + imported_on_line_number = index, + from_line = 0, + to_line = 0 + } + + imported_titles[import.prefix] = import.path.hash() + + var origin_hash: int = -1 + for hash_value in known_imports.keys(): + if known_imports[hash_value] == ".": + origin_hash = hash_value + + # Replace any titles or jump points with references to the files they point to (event if they point to their own file) + for i in range(0, content.size()): + var line = content[i] + if is_title_line(line): + var title = extract_title(line) + if "/" in line: + var bits = title.split("/") + content[i] = "~ %s/%s" % [imported_titles[bits[0]], bits[1]] + else: + content[i] = "~ %s/%s" % [str(path.hash()), title] + + elif "=>< " in line: + var jump: String = line.substr(line.find("=>< ") + "=>< ".length()).strip_edges() + if "/" in jump: + var bits: PackedStringArray = jump.split("/") + var title_hash: int = imported_titles[bits[0]] + if title_hash == origin_hash: + content[i] = "%s=>< %s" % [line.split("=>< ")[0], bits[1]] + else: + content[i] = "%s=>< %s/%s" % [line.split("=>< ")[0], title_hash, bits[1]] + + elif not jump in ["END", "END!"]: + content[i] = "%s=>< %s/%s" % [line.split("=>< ")[0], str(path.hash()), jump] + + elif "=> " in line: + var jump: String = line.substr(line.find("=> ") + "=> ".length()).strip_edges() + if "/" in jump: + var bits: PackedStringArray = jump.split("/") + var title_hash: int = imported_titles[bits[0]] + if title_hash == origin_hash: + content[i] = "%s=> %s" % [line.split("=> ")[0], bits[1]] + else: + content[i] = "%s=> %s/%s" % [line.split("=> ")[0], title_hash, bits[1]] + + elif not jump in ["END", "END!"]: + content[i] = "%s=> %s/%s" % [line.split("=> ")[0], str(path.hash()), jump] + + imported_paths.append(path) + known_imports[path.hash()] = "\n".join(content) + "\n=> END\n" + return OK + else: + return ERR_FILE_NOT_FOUND + + +func extract_import_path_and_name(line: String) -> Dictionary: + var found: RegExMatch = IMPORT_REGEX.search(line) + if found: + return { + path = found.strings[found.names.path], + prefix = found.strings[found.names.prefix] + } + else: + return {} + + +func extract_title(line: String) -> String: + return line.substr(2).strip_edges() + + +func extract_translation(line: String) -> String: + # Find a static translation key, eg. [ID:something] + var found: RegExMatch = TRANSLATION_REGEX.search(line) + if found: + return found.strings[found.names.tr] + else: + return "" + + +func extract_response_prompt(line: String) -> String: + # Find just the text prompt from a response, ignoring any conditions or gotos + line = line.substr(2) + if " [if " in line: + line = line.substr(0, line.find(" [if ")) + if " =>" in line: + line = line.substr(0, line.find(" =>")) + + # Without the translation key if there is one + var translation_key: String = extract_translation(line) + if translation_key: + line = line.replace("[ID:%s]" % translation_key, "") + + return line.replace("\\n", "\n").strip_edges() + + +func parse_response_character_and_text(id: int, text: String, line: Dictionary, indent_size: int, parsed_lines: Dictionary) -> void: + var bits = Array(text.strip_edges().split(": ")) + line["character"] = bits.pop_front().strip_edges() + line["character_replacements"] = extract_dialogue_replacements(line.character, line.character.length() + 2 + indent_size) + for replacement in line.character_replacements: + if replacement.has("error"): + add_error(id, replacement.index, replacement.error) + + if not line["character"] in character_names: + character_names.append(line["character"]) + + line["text"] = ": ".join(bits).replace("!ESCAPED_COLON!", ":").strip_edges() + + if line.get("translation_key", null) == null: + line["translation_key"] = line.text + + +func extract_mutation(line: String) -> Dictionary: + var found: RegExMatch = MUTATION_REGEX.search(line) + + if not found: + return { + index = 0, + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + + if found.names.has("mutation"): + var expression: Array = tokenise(found.strings[found.names.mutation], DialogueConstants.TYPE_MUTATION, found.get_start("mutation")) + if expression.size() == 0: + return { + index = found.get_start("mutation"), + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + elif expression[0].type == DialogueConstants.TYPE_ERROR: + return { + index = expression[0].index, + error = expression[0].value + } + else: + return { + expression = expression, + is_blocking = not "!" in found.strings[found.names.keyword] + } + + else: + return { + index = found.get_start(), + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + + +func extract_condition(raw_line: String, is_wrapped: bool, index: int) -> Dictionary: + var condition: Dictionary = {} + + var regex: RegEx = WRAPPED_CONDITION_REGEX if is_wrapped else CONDITION_REGEX + var found: RegExMatch = regex.search(raw_line) + + if found == null: + return { + index = 0, + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + + var raw_condition: String = found.strings[found.names.condition] + var expression: Array = tokenise(raw_condition, DialogueConstants.TYPE_CONDITION, index + found.get_start("condition")) + + if expression.size() == 0: + return { + index = index + found.get_start("condition"), + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + elif expression[0].type == DialogueConstants.TYPE_ERROR: + return { + index = expression[0].index, + error = expression[0].value + } + else: + return { + expression = expression + } + + +func extract_dialogue_replacements(text: String, index: int) -> Array[Dictionary]: + var founds: Array[RegExMatch] = REPLACEMENTS_REGEX.search_all(text) + + if founds == null or founds.size() == 0: + return [] + + var replacements: Array[Dictionary] = [] + for found in founds: + var replacement: Dictionary = {} + var value_in_text: String = found.strings[1] + var expression: Array = tokenise(value_in_text, DialogueConstants.TYPE_DIALOGUE, index + found.get_start(1)) + if expression.size() == 0: + replacement = { + index = index + found.get_start(1), + error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION + } + elif expression[0].type == DialogueConstants.TYPE_ERROR: + replacement = { + index = expression[0].index, + error = expression[0].value + } + else: + replacement = { + value_in_text = "{{%s}}" % value_in_text, + expression = expression + } + replacements.append(replacement) + + return replacements + + +func extract_goto(line: String) -> String: + var found: RegExMatch = GOTO_REGEX.search(line) + + if found == null: return DialogueConstants.ID_ERROR + + var title: String = found.strings[found.names.jump_to_title].strip_edges() + + if " " in title or title == "": + return DialogueConstants.ID_ERROR_INVALID_TITLE + + # "=> END!" means end the conversation + if title == "END!": + return DialogueConstants.ID_END_CONVERSATION + # "=> END" means end the current title (and go back to the previous one if there is one + # in the stack) + elif title == "END": + return DialogueConstants.ID_END + + elif titles.has(title): + return titles.get(title) + else: + return DialogueConstants.ID_ERROR + + +func extract_tags(line: String) -> ResolvedTagData: + var resolved_tags: PackedStringArray = [] + var tag_matches: Array[RegExMatch] = TAGS_REGEX.search_all(line) + for tag_match in tag_matches: + line = line.replace(tag_match.get_string(), "") + var tags = tag_match.get_string().replace("[#", "").replace("]", "").replace(", ", ",").split(",") + for tag in tags: + tag = tag.replace("#", "") + if not tag in resolved_tags: + resolved_tags.append(tag) + + return ResolvedTagData.new({ + tags = resolved_tags, + line_without_tags = line + }) + + +func extract_markers(line: String) -> ResolvedLineData: + var text: String = line + var pauses: Dictionary = {} + var speeds: Dictionary = {} + var mutations: Array[Array] = [] + var bbcodes: Array = [] + var time: String = "" + + # Remove any escaped brackets (ie. "\[") + var escaped_open_brackets: PackedInt32Array = [] + var escaped_close_brackets: PackedInt32Array = [] + for i in range(0, text.length() - 1): + if text.substr(i, 2) == "\\[": + text = text.substr(0, i) + "!" + text.substr(i + 2) + escaped_open_brackets.append(i) + elif text.substr(i, 2) == "\\]": + text = text.substr(0, i) + "!" + text.substr(i + 2) + escaped_close_brackets.append(i) + + # Extract all of the BB codes so that we know the actual text (we could do this easier with + # a RichTextLabel but then we'd need to await idle_frame which is annoying) + var bbcode_positions = find_bbcode_positions_in_string(text) + var accumulaive_length_offset = 0 + for position in bbcode_positions: + # Ignore our own markers + if position.code in ["wait", "speed", "/speed", "do", "do!", "set", "next", "if", "else", "/if"]: + continue + + bbcodes.append({ + bbcode = position.bbcode, + start = position.start, + offset_start = position.start - accumulaive_length_offset + }) + accumulaive_length_offset += position.bbcode.length() + + for bb in bbcodes: + text = text.substr(0, bb.offset_start) + text.substr(bb.offset_start + bb.bbcode.length()) + + # Now find any dialogue markers + var next_bbcode_position = find_bbcode_positions_in_string(text, false) + var limit = 0 + while next_bbcode_position.size() > 0 and limit < 1000: + limit += 1 + + var bbcode = next_bbcode_position[0] + + var index = bbcode.start + var code = bbcode.code + var raw_args = bbcode.raw_args + var args = {} + if code in ["do", "do!", "set"]: + args["value"] = extract_mutation("%s %s" % [code, raw_args]) + else: + # Could be something like: + # "=1.0" + # " rate=20 level=10" + if raw_args and raw_args[0] == "=": + raw_args = "value" + raw_args + for pair in raw_args.strip_edges().split(" "): + if "=" in pair: + var bits = pair.split("=") + args[bits[0]] = bits[1] + + match code: + "wait": + if pauses.has(index): + pauses[index] += args.get("value").to_float() + else: + pauses[index] = args.get("value").to_float() + "speed": + speeds[index] = args.get("value").to_float() + "/speed": + speeds[index] = 1.0 + "do", "do!", "set": + mutations.append([index, args.get("value")]) + "next": + time = args.get("value") if args.has("value") else "0" + + # Find any BB codes that are after this index and remove the length from their start + var length = bbcode.bbcode.length() + for bb in bbcodes: + if bb.offset_start > bbcode.start: + bb.offset_start -= length + bb.start -= length + + # Find any escaped brackets after this that need moving + for i in range(0, escaped_open_brackets.size()): + if escaped_open_brackets[i] > bbcode.start: + escaped_open_brackets[i] -= length + for i in range(0, escaped_close_brackets.size()): + if escaped_close_brackets[i] > bbcode.start: + escaped_close_brackets[i] -= length + + text = text.substr(0, index) + text.substr(index + length) + next_bbcode_position = find_bbcode_positions_in_string(text, false) + + # Put the BB Codes back in + for bb in bbcodes: + text = text.insert(bb.start, bb.bbcode) + + # Put the escaped brackets back in + for index in escaped_open_brackets: + text = text.left(index) + "[" + text.right(text.length() - index - 1) + for index in escaped_close_brackets: + text = text.left(index) + "]" + text.right(text.length() - index - 1) + + return ResolvedLineData.new({ + text = text, + pauses = pauses, + speeds = speeds, + mutations = mutations, + time = time + }) + + +func find_bbcode_positions_in_string(string: String, find_all: bool = true) -> Array[Dictionary]: + if not "[" in string: return [] + + var positions: Array[Dictionary] = [] + + var open_brace_count: int = 0 + var start: int = 0 + var bbcode: String = "" + var code: String = "" + var is_finished_code: bool = false + for i in range(0, string.length()): + if string[i] == "[": + if open_brace_count == 0: + start = i + bbcode = "" + code = "" + is_finished_code = false + open_brace_count += 1 + + else: + if not is_finished_code and (string[i].to_upper() != string[i] or string[i] == "/" or string[i] == "!"): + code += string[i] + else: + is_finished_code = true + + if open_brace_count > 0: + bbcode += string[i] + + if string[i] == "]": + open_brace_count -= 1 + if open_brace_count == 0 and not code in ["if", "else", "/if"]: + positions.append({ + bbcode = bbcode, + code = code, + start = start, + raw_args = bbcode.substr(code.length() + 1, bbcode.length() - code.length() - 2).strip_edges() + }) + + if not find_all: + return positions + + return positions + + +func tokenise(text: String, line_type: String, index: int) -> Array: + var tokens: Array[Dictionary] = [] + var limit: int = 0 + while text.strip_edges() != "" and limit < 1000: + limit += 1 + var found = find_match(text) + if found.size() > 0: + tokens.append({ + index = index, + type = found.type, + value = found.value + }) + index += found.value.length() + text = found.remaining_text + elif text.begins_with(" "): + index += 1 + text = text.substr(1) + else: + return build_token_tree_error(DialogueConstants.ERR_INVALID_EXPRESSION, index) + + return build_token_tree(tokens, line_type, "")[0] + + +func build_token_tree_error(error: int, index: int) -> Array: + return [{ type = DialogueConstants.TOKEN_ERROR, value = error, index = index }] + + +func build_token_tree(tokens: Array[Dictionary], line_type: String, expected_close_token: String) -> Array: + var tree: Array[Dictionary] = [] + var limit = 0 + while tokens.size() > 0 and limit < 1000: + limit += 1 + var token = tokens.pop_front() + + var error = check_next_token(token, tokens, line_type, expected_close_token) + if error != OK: + return [build_token_tree_error(error, token.index), tokens] + + match token.type: + DialogueConstants.TOKEN_FUNCTION: + var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_PARENS_CLOSE) + + if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: + return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] + + tree.append({ + type = DialogueConstants.TOKEN_FUNCTION, + # Consume the trailing "(" + function = token.value.substr(0, token.value.length() - 1), + value = tokens_to_list(sub_tree[0]) + }) + tokens = sub_tree[1] + + DialogueConstants.TOKEN_DICTIONARY_REFERENCE: + var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACKET_CLOSE) + + if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: + return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] + + var args = tokens_to_list(sub_tree[0]) + if args.size() != 1: + return [build_token_tree_error(DialogueConstants.ERR_INVALID_INDEX, token.index), tokens] + + tree.append({ + type = DialogueConstants.TOKEN_DICTIONARY_REFERENCE, + # Consume the trailing "[" + variable = token.value.substr(0, token.value.length() - 1), + value = args[0] + }) + tokens = sub_tree[1] + + DialogueConstants.TOKEN_BRACE_OPEN: + var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACE_CLOSE) + + if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: + return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] + + var t = sub_tree[0] + for i in range(0, t.size() - 2): + # Convert Lua style dictionaries to string keys + if t[i].type == DialogueConstants.TOKEN_VARIABLE and t[i+1].type == DialogueConstants.TOKEN_ASSIGNMENT: + t[i].type = DialogueConstants.TOKEN_STRING + t[i+1].type = DialogueConstants.TOKEN_COLON + t[i+1].erase("value") + + tree.append({ + type = DialogueConstants.TOKEN_DICTIONARY, + value = tokens_to_dictionary(sub_tree[0]) + }) + + tokens = sub_tree[1] + + DialogueConstants.TOKEN_BRACKET_OPEN: + var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACKET_CLOSE) + + if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: + return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] + + var type = DialogueConstants.TOKEN_ARRAY + var value = tokens_to_list(sub_tree[0]) + + # See if this is referencing a nested dictionary value + if tree.size() > 0: + var previous_token = tree[tree.size() - 1] + if previous_token.type in [DialogueConstants.TOKEN_DICTIONARY_REFERENCE, DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE]: + type = DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE + value = value[0] + + tree.append({ + type = type, + value = value + }) + tokens = sub_tree[1] + + DialogueConstants.TOKEN_PARENS_OPEN: + var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_PARENS_CLOSE) + + if sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: + return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] + + tree.append({ + type = DialogueConstants.TOKEN_GROUP, + value = sub_tree[0] + }) + tokens = sub_tree[1] + + DialogueConstants.TOKEN_PARENS_CLOSE, \ + DialogueConstants.TOKEN_BRACE_CLOSE, \ + DialogueConstants.TOKEN_BRACKET_CLOSE: + if token.type != expected_close_token: + return [build_token_tree_error(DialogueConstants.ERR_UNEXPECTED_CLOSING_BRACKET, token.index), tokens] + + return [tree, tokens] + + DialogueConstants.TOKEN_NOT: + # Double nots negate each other + if tokens.size() > 0 and tokens.front().type == DialogueConstants.TOKEN_NOT: + tokens.pop_front() + else: + tree.append({ + type = token.type + }) + + DialogueConstants.TOKEN_COMMA, \ + DialogueConstants.TOKEN_COLON, \ + DialogueConstants.TOKEN_DOT: + tree.append({ + type = token.type + }) + + DialogueConstants.TOKEN_COMPARISON, \ + DialogueConstants.TOKEN_ASSIGNMENT, \ + DialogueConstants.TOKEN_OPERATOR, \ + DialogueConstants.TOKEN_AND_OR, \ + DialogueConstants.TOKEN_VARIABLE: \ + tree.append({ + type = token.type, + value = token.value.strip_edges() + }) + + DialogueConstants.TOKEN_STRING: + tree.append({ + type = token.type, + value = token.value.substr(1, token.value.length() - 2) + }) + + DialogueConstants.TOKEN_CONDITION: + return [build_token_tree_error(DialogueConstants.ERR_UNEXPECTED_CONDITION, token.index), token] + + DialogueConstants.TOKEN_BOOL: + tree.append({ + type = token.type, + value = token.value.to_lower() == "true" + }) + + DialogueConstants.TOKEN_NUMBER: + var value = token.value.to_float() if "." in token.value else token.value.to_int() + # If previous token is a number and this one is a negative number then + # inject a minus operator token in between them. + if tree.size() > 0 and token.value.begins_with("-") and tree[tree.size() - 1].type == DialogueConstants.TOKEN_NUMBER: + tree.append(({ + type = DialogueConstants.TOKEN_OPERATOR, + value = "-" + })) + tree.append({ + type = token.type, + value = -1 * value + }) + else: + tree.append({ + type = token.type, + value = value + }) + + if expected_close_token != "": + var index: int = tokens[0].index if tokens.size() > 0 else 0 + return [build_token_tree_error(DialogueConstants.ERR_MISSING_CLOSING_BRACKET, index), tokens] + + return [tree, tokens] + + +func check_next_token(token: Dictionary, next_tokens: Array[Dictionary], line_type: String, expected_close_token: String) -> Error: + var next_token: Dictionary = { type = null } + if next_tokens.size() > 0: + next_token = next_tokens.front() + + # Guard for assigning in a condition. If the assignment token isn't inside a Lua dictionary + # then it's an unexpected assignment in a condition line. + if token.type == DialogueConstants.TOKEN_ASSIGNMENT and line_type == DialogueConstants.TYPE_CONDITION and not next_tokens.any(func(t): return t.type == expected_close_token): + return DialogueConstants.ERR_UNEXPECTED_ASSIGNMENT + + # Special case for a negative number after this one + if token.type == DialogueConstants.TOKEN_NUMBER and next_token.type == DialogueConstants.TOKEN_NUMBER and next_token.value.begins_with("-"): + return OK + + var expected_token_types = [] + var unexpected_token_types = [] + match token.type: + DialogueConstants.TOKEN_FUNCTION, \ + DialogueConstants.TOKEN_PARENS_OPEN: + unexpected_token_types = [ + null, + DialogueConstants.TOKEN_COMMA, + DialogueConstants.TOKEN_COLON, + DialogueConstants.TOKEN_COMPARISON, + DialogueConstants.TOKEN_ASSIGNMENT, + DialogueConstants.TOKEN_OPERATOR, + DialogueConstants.TOKEN_AND_OR, + DialogueConstants.TOKEN_DOT + ] + + DialogueConstants.TOKEN_BRACKET_CLOSE: + unexpected_token_types = [ + DialogueConstants.TOKEN_NOT, + DialogueConstants.TOKEN_BOOL, + DialogueConstants.TOKEN_STRING, + DialogueConstants.TOKEN_NUMBER, + DialogueConstants.TOKEN_VARIABLE + ] + + DialogueConstants.TOKEN_BRACE_OPEN: + expected_token_types = [ + DialogueConstants.TOKEN_STRING, + DialogueConstants.TOKEN_VARIABLE, + DialogueConstants.TOKEN_NUMBER, + DialogueConstants.TOKEN_BRACE_CLOSE + ] + + DialogueConstants.TOKEN_PARENS_CLOSE, \ + DialogueConstants.TOKEN_BRACE_CLOSE: + unexpected_token_types = [ + DialogueConstants.TOKEN_NOT, + DialogueConstants.TOKEN_ASSIGNMENT, + DialogueConstants.TOKEN_BOOL, + DialogueConstants.TOKEN_STRING, + DialogueConstants.TOKEN_NUMBER, + DialogueConstants.TOKEN_VARIABLE + ] + + DialogueConstants.TOKEN_COMPARISON, \ + DialogueConstants.TOKEN_OPERATOR, \ + DialogueConstants.TOKEN_COMMA, \ + DialogueConstants.TOKEN_DOT, \ + DialogueConstants.TOKEN_NOT, \ + DialogueConstants.TOKEN_AND_OR, \ + DialogueConstants.TOKEN_DICTIONARY_REFERENCE: + unexpected_token_types = [ + null, + DialogueConstants.TOKEN_COMMA, + DialogueConstants.TOKEN_COLON, + DialogueConstants.TOKEN_COMPARISON, + DialogueConstants.TOKEN_ASSIGNMENT, + DialogueConstants.TOKEN_OPERATOR, + DialogueConstants.TOKEN_AND_OR, + DialogueConstants.TOKEN_PARENS_CLOSE, + DialogueConstants.TOKEN_BRACE_CLOSE, + DialogueConstants.TOKEN_BRACKET_CLOSE, + DialogueConstants.TOKEN_DOT + ] + + DialogueConstants.TOKEN_COLON: + unexpected_token_types = [ + DialogueConstants.TOKEN_COMMA, + DialogueConstants.TOKEN_COLON, + DialogueConstants.TOKEN_COMPARISON, + DialogueConstants.TOKEN_ASSIGNMENT, + DialogueConstants.TOKEN_OPERATOR, + DialogueConstants.TOKEN_AND_OR, + DialogueConstants.TOKEN_PARENS_CLOSE, + DialogueConstants.TOKEN_BRACE_CLOSE, + DialogueConstants.TOKEN_BRACKET_CLOSE, + DialogueConstants.TOKEN_DOT + ] + + DialogueConstants.TOKEN_BOOL, \ + DialogueConstants.TOKEN_STRING, \ + DialogueConstants.TOKEN_NUMBER: + unexpected_token_types = [ + DialogueConstants.TOKEN_NOT, + DialogueConstants.TOKEN_ASSIGNMENT, + DialogueConstants.TOKEN_BOOL, + DialogueConstants.TOKEN_STRING, + DialogueConstants.TOKEN_NUMBER, + DialogueConstants.TOKEN_VARIABLE, + DialogueConstants.TOKEN_FUNCTION, + DialogueConstants.TOKEN_PARENS_OPEN, + DialogueConstants.TOKEN_BRACE_OPEN, + DialogueConstants.TOKEN_BRACKET_OPEN + ] + + DialogueConstants.TOKEN_VARIABLE: + unexpected_token_types = [ + DialogueConstants.TOKEN_NOT, + DialogueConstants.TOKEN_BOOL, + DialogueConstants.TOKEN_STRING, + DialogueConstants.TOKEN_NUMBER, + DialogueConstants.TOKEN_VARIABLE, + DialogueConstants.TOKEN_FUNCTION, + DialogueConstants.TOKEN_PARENS_OPEN, + DialogueConstants.TOKEN_BRACE_OPEN, + DialogueConstants.TOKEN_BRACKET_OPEN + ] + + if (expected_token_types.size() > 0 and not next_token.type in expected_token_types or unexpected_token_types.size() > 0 and next_token.type in unexpected_token_types): + match next_token.type: + null: + return DialogueConstants.ERR_UNEXPECTED_END_OF_EXPRESSION + + DialogueConstants.TOKEN_FUNCTION: + return DialogueConstants.ERR_UNEXPECTED_FUNCTION + + DialogueConstants.TOKEN_PARENS_OPEN, \ + DialogueConstants.TOKEN_PARENS_CLOSE: + return DialogueConstants.ERR_UNEXPECTED_BRACKET + + DialogueConstants.TOKEN_COMPARISON, \ + DialogueConstants.TOKEN_ASSIGNMENT, \ + DialogueConstants.TOKEN_OPERATOR, \ + DialogueConstants.TOKEN_NOT, \ + DialogueConstants.TOKEN_AND_OR: + return DialogueConstants.ERR_UNEXPECTED_OPERATOR + + DialogueConstants.TOKEN_COMMA: + return DialogueConstants.ERR_UNEXPECTED_COMMA + DialogueConstants.TOKEN_COLON: + return DialogueConstants.ERR_UNEXPECTED_COLON + DialogueConstants.TOKEN_DOT: + return DialogueConstants.ERR_UNEXPECTED_DOT + + DialogueConstants.TOKEN_BOOL: + return DialogueConstants.ERR_UNEXPECTED_BOOLEAN + DialogueConstants.TOKEN_STRING: + return DialogueConstants.ERR_UNEXPECTED_STRING + DialogueConstants.TOKEN_NUMBER: + return DialogueConstants.ERR_UNEXPECTED_NUMBER + DialogueConstants.TOKEN_VARIABLE: + return DialogueConstants.ERR_UNEXPECTED_VARIABLE + + return DialogueConstants.ERR_INVALID_EXPRESSION + + return OK + + +func tokens_to_list(tokens: Array[Dictionary]) -> Array[Array]: + var list: Array[Array] = [] + var current_item: Array[Dictionary] = [] + for token in tokens: + if token.type == DialogueConstants.TOKEN_COMMA: + list.append(current_item) + current_item = [] + else: + current_item.append(token) + + if current_item.size() > 0: + list.append(current_item) + + return list + + +func tokens_to_dictionary(tokens: Array[Dictionary]) -> Dictionary: + var dictionary = {} + for i in range(0, tokens.size()): + if tokens[i].type == DialogueConstants.TOKEN_COLON: + if tokens.size() == i + 2: + dictionary[tokens[i-1]] = tokens[i+1] + else: + dictionary[tokens[i-1]] = { type = DialogueConstants.TOKEN_GROUP, value = tokens.slice(i+1) } + + return dictionary + + +func find_match(input: String) -> Dictionary: + for key in TOKEN_DEFINITIONS.keys(): + var regex = TOKEN_DEFINITIONS.get(key) + var found = regex.search(input) + if found: + return { + type = key, + remaining_text = input.substr(found.strings[0].length()), + value = found.strings[0] + } + + return {} diff --git a/addons/dialogue_manager/components/resolved_line_data.gd b/addons/dialogue_manager/components/resolved_line_data.gd new file mode 100644 index 0000000..1073586 --- /dev/null +++ b/addons/dialogue_manager/components/resolved_line_data.gd @@ -0,0 +1,15 @@ +extends RefCounted + +var text: String = "" +var pauses: Dictionary = {} +var speeds: Dictionary = {} +var mutations: Array[Array] = [] +var time: String = "" + + +func _init(data: Dictionary) -> void: + text = data.text + pauses = data.pauses + speeds = data.speeds + mutations = data.mutations + time = data.time diff --git a/addons/dialogue_manager/components/resolved_tag_data.gd b/addons/dialogue_manager/components/resolved_tag_data.gd new file mode 100644 index 0000000..728cc42 --- /dev/null +++ b/addons/dialogue_manager/components/resolved_tag_data.gd @@ -0,0 +1,10 @@ +extends RefCounted + + +var tags: PackedStringArray = [] +var line_without_tags: String = "" + + +func _init(data: Dictionary) -> void: + tags = data.tags + line_without_tags = data.line_without_tags diff --git a/addons/dialogue_manager/components/search_and_replace.gd b/addons/dialogue_manager/components/search_and_replace.gd new file mode 100644 index 0000000..c47ac5b --- /dev/null +++ b/addons/dialogue_manager/components/search_and_replace.gd @@ -0,0 +1,210 @@ +@tool +extends VBoxContainer + + +signal open_requested() +signal close_requested() + + +const DialogueConstants = preload("../constants.gd") + + +@onready var input: LineEdit = $Search/Input +@onready var result_label: Label = $Search/ResultLabel +@onready var previous_button: Button = $Search/PreviousButton +@onready var next_button: Button = $Search/NextButton +@onready var match_case_button: CheckBox = $Search/MatchCaseCheckBox +@onready var replace_check_button: CheckButton = $Search/ReplaceCheckButton +@onready var replace_panel: HBoxContainer = $Replace +@onready var replace_input: LineEdit = $Replace/Input +@onready var replace_button: Button = $Replace/ReplaceButton +@onready var replace_all_button: Button = $Replace/ReplaceAllButton + +# The code edit we will be affecting (for some reason exporting this didn't work) +var code_edit: CodeEdit: + set(next_code_edit): + code_edit = next_code_edit + code_edit.gui_input.connect(_on_text_edit_gui_input) + code_edit.text_changed.connect(_on_text_edit_text_changed) + get: + return code_edit + +var results: Array = [] +var result_index: int = -1: + set(next_result_index): + result_index = next_result_index + if results.size() > 0: + var r = results[result_index] + code_edit.set_caret_line(r[0]) + code_edit.select(r[0], r[1], r[0], r[1] + r[2]) + else: + result_index = -1 + if is_instance_valid(code_edit): + code_edit.deselect() + + result_label.text = DialogueConstants.translate(&"n_of_n").format({ index = result_index + 1, total = results.size() }) + get: + return result_index + + +func _ready() -> void: + apply_theme() + + input.placeholder_text = DialogueConstants.translate(&"search.placeholder") + previous_button.tooltip_text = DialogueConstants.translate(&"search.previous") + next_button.tooltip_text = DialogueConstants.translate(&"search.next") + match_case_button.text = DialogueConstants.translate(&"search.match_case") + $Search/ReplaceCheckButton.text = DialogueConstants.translate(&"search.toggle_replace") + replace_button.text = DialogueConstants.translate(&"search.replace") + replace_all_button.text = DialogueConstants.translate(&"search.replace_all") + $Replace/ReplaceLabel.text = DialogueConstants.translate(&"search.replace_with") + + self.result_index = -1 + + replace_panel.hide() + replace_button.disabled = true + replace_all_button.disabled = true + + hide() + + +func focus_line_edit() -> void: + input.grab_focus() + input.select_all() + + +func apply_theme() -> void: + if is_instance_valid(previous_button): + previous_button.icon = get_theme_icon("ArrowLeft", "EditorIcons") + if is_instance_valid(next_button): + next_button.icon = get_theme_icon("ArrowRight", "EditorIcons") + + +# Find text in the code +func search(text: String = "", default_result_index: int = 0) -> void: + results.clear() + + if text == "": + text = input.text + + var lines = code_edit.text.split("\n") + for line_number in range(0, lines.size()): + var line = lines[line_number] + + var column = find_in_line(line, text, 0) + while column > -1: + results.append([line_number, column, text.length()]) + column = find_in_line(line, text, column + 1) + + if results.size() > 0: + replace_button.disabled = false + replace_all_button.disabled = false + else: + replace_button.disabled = true + replace_all_button.disabled = true + + self.result_index = clamp(default_result_index, 0, results.size() - 1) + + +# Find text in a string and match case if requested +func find_in_line(line: String, text: String, from_index: int = 0) -> int: + if match_case_button.button_pressed: + return line.find(text, from_index) + else: + return line.findn(text, from_index) + + +### Signals + + +func _on_text_edit_gui_input(event: InputEvent) -> void: + if event is InputEventKey and event.is_pressed(): + match event.as_text(): + "Ctrl+F", "Command+F": + open_requested.emit() + "Ctrl+Shift+R", "Command+Shift+R": + replace_check_button.set_pressed(true) + open_requested.emit() + + +func _on_text_edit_text_changed() -> void: + results.clear() + + +func _on_search_and_replace_theme_changed() -> void: + apply_theme() + + +func _on_input_text_changed(new_text: String) -> void: + search(new_text) + + +func _on_previous_button_pressed() -> void: + self.result_index = wrapi(result_index - 1, 0, results.size()) + + +func _on_next_button_pressed() -> void: + self.result_index = wrapi(result_index + 1, 0, results.size()) + + +func _on_search_and_replace_visibility_changed() -> void: + if is_instance_valid(input): + if visible: + input.grab_focus() + var selection = code_edit.get_selected_text() + if input.text == "" and selection != "": + input.text = selection + search(selection) + else: + search() + else: + input.text = "" + + +func _on_input_gui_input(event: InputEvent) -> void: + if event is InputEventKey and event.is_pressed(): + match event.as_text(): + "Enter": + search(input.text) + "Escape": + emit_signal("close_requested") + + +func _on_replace_button_pressed() -> void: + if result_index == -1: return + + # Replace the selection at result index + var r: Array = results[result_index] + var lines: PackedStringArray = code_edit.text.split("\n") + var line: String = lines[r[0]] + line = line.substr(0, r[1]) + replace_input.text + line.substr(r[1] + r[2]) + lines[r[0]] = line + code_edit.text = "\n".join(lines) + search(input.text, result_index) + code_edit.text_changed.emit() + + +func _on_replace_all_button_pressed() -> void: + if match_case_button.button_pressed: + code_edit.text = code_edit.text.replace(input.text, replace_input.text) + else: + code_edit.text = code_edit.text.replacen(input.text, replace_input.text) + search() + code_edit.text_changed.emit() + + +func _on_replace_check_button_toggled(button_pressed: bool) -> void: + replace_panel.visible = button_pressed + if button_pressed: + replace_input.grab_focus() + + +func _on_input_focus_entered() -> void: + if results.size() == 0: + search() + else: + self.result_index = result_index + + +func _on_match_case_check_box_toggled(button_pressed: bool) -> void: + search() diff --git a/addons/dialogue_manager/components/search_and_replace.tscn b/addons/dialogue_manager/components/search_and_replace.tscn new file mode 100644 index 0000000..82dd60d --- /dev/null +++ b/addons/dialogue_manager/components/search_and_replace.tscn @@ -0,0 +1,87 @@ +[gd_scene load_steps=2 format=3 uid="uid://gr8nakpbrhby"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/search_and_replace.gd" id="1_8oj1f"] + +[node name="SearchAndReplace" type="VBoxContainer"] +visible = false +anchors_preset = 10 +anchor_right = 1.0 +offset_bottom = 31.0 +grow_horizontal = 2 +size_flags_horizontal = 3 +script = ExtResource("1_8oj1f") + +[node name="Search" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="Input" type="LineEdit" parent="Search"] +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "Text to search for" +metadata/_edit_use_custom_anchors = true + +[node name="MatchCaseCheckBox" type="CheckBox" parent="Search"] +layout_mode = 2 +text = "Match case" + +[node name="VSeparator" type="VSeparator" parent="Search"] +layout_mode = 2 + +[node name="PreviousButton" type="Button" parent="Search"] +layout_mode = 2 +tooltip_text = "Previous" +flat = true + +[node name="ResultLabel" type="Label" parent="Search"] +layout_mode = 2 +text = "0 of 0" + +[node name="NextButton" type="Button" parent="Search"] +layout_mode = 2 +tooltip_text = "Next" +flat = true + +[node name="VSeparator2" type="VSeparator" parent="Search"] +layout_mode = 2 + +[node name="ReplaceCheckButton" type="CheckButton" parent="Search"] +layout_mode = 2 +text = "Replace" + +[node name="Replace" type="HBoxContainer" parent="."] +visible = false +layout_mode = 2 + +[node name="ReplaceLabel" type="Label" parent="Replace"] +layout_mode = 2 +text = "Replace with:" + +[node name="Input" type="LineEdit" parent="Replace"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ReplaceButton" type="Button" parent="Replace"] +layout_mode = 2 +disabled = true +text = "Replace" +flat = true + +[node name="ReplaceAllButton" type="Button" parent="Replace"] +layout_mode = 2 +disabled = true +text = "Replace all" +flat = true + +[connection signal="theme_changed" from="." to="." method="_on_search_and_replace_theme_changed"] +[connection signal="visibility_changed" from="." to="." method="_on_search_and_replace_visibility_changed"] +[connection signal="focus_entered" from="Search/Input" to="." method="_on_input_focus_entered"] +[connection signal="gui_input" from="Search/Input" to="." method="_on_input_gui_input"] +[connection signal="text_changed" from="Search/Input" to="." method="_on_input_text_changed"] +[connection signal="toggled" from="Search/MatchCaseCheckBox" to="." method="_on_match_case_check_box_toggled"] +[connection signal="pressed" from="Search/PreviousButton" to="." method="_on_previous_button_pressed"] +[connection signal="pressed" from="Search/NextButton" to="." method="_on_next_button_pressed"] +[connection signal="toggled" from="Search/ReplaceCheckButton" to="." method="_on_replace_check_button_toggled"] +[connection signal="focus_entered" from="Replace/Input" to="." method="_on_input_focus_entered"] +[connection signal="gui_input" from="Replace/Input" to="." method="_on_input_gui_input"] +[connection signal="pressed" from="Replace/ReplaceButton" to="." method="_on_replace_button_pressed"] +[connection signal="pressed" from="Replace/ReplaceAllButton" to="." method="_on_replace_all_button_pressed"] diff --git a/addons/dialogue_manager/components/title_list.gd b/addons/dialogue_manager/components/title_list.gd new file mode 100644 index 0000000..ee7cd13 --- /dev/null +++ b/addons/dialogue_manager/components/title_list.gd @@ -0,0 +1,67 @@ +@tool +extends VBoxContainer + +signal title_selected(title: String) + + +const DialogueConstants = preload("../constants.gd") + + +@onready var filter_edit: LineEdit = $FilterEdit +@onready var list: ItemList = $List + +var titles: PackedStringArray: + set(next_titles): + titles = next_titles + apply_filter() + get: + return titles + +var filter: String: + set(next_filter): + filter = next_filter + apply_filter() + get: + return filter + + +func _ready() -> void: + apply_theme() + + filter_edit.placeholder_text = DialogueConstants.translate(&"titles_list.filter") + + +func select_title(title: String) -> void: + list.deselect_all() + for i in range(0, list.get_item_count()): + if list.get_item_text(i) == title.strip_edges(): + list.select(i) + + +func apply_filter() -> void: + list.clear() + for title in titles: + if filter == "" or filter.to_lower() in title.to_lower(): + list.add_item(title.strip_edges()) + + +func apply_theme() -> void: + if is_instance_valid(filter_edit): + filter_edit.right_icon = get_theme_icon("Search", "EditorIcons") + + +### Signals + + +func _on_theme_changed() -> void: + apply_theme() + + +func _on_filter_edit_text_changed(new_text: String) -> void: + self.filter = new_text + + +func _on_list_item_clicked(index: int, at_position: Vector2, mouse_button_index: int) -> void: + if mouse_button_index == MOUSE_BUTTON_LEFT: + var title = list.get_item_text(index) + title_selected.emit(title) diff --git a/addons/dialogue_manager/components/title_list.tscn b/addons/dialogue_manager/components/title_list.tscn new file mode 100644 index 0000000..3e5c9a0 --- /dev/null +++ b/addons/dialogue_manager/components/title_list.tscn @@ -0,0 +1,45 @@ +[gd_scene load_steps=4 format=3 uid="uid://ctns6ouwwd68i"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/title_list.gd" id="1_5qqmd"] + +[sub_resource type="Image" id="Image_o5dqs"] +data = { +"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), +"format": "RGBA8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id="ImageTexture_ekmpw"] +image = SubResource("Image_o5dqs") + +[node name="TitleList" type="VBoxContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("1_5qqmd") + +[node name="FilterEdit" type="LineEdit" parent="."] +layout_mode = 2 +offset_right = 1152.0 +offset_bottom = 31.0 +placeholder_text = "Filter titles" +clear_button_enabled = true +right_icon = SubResource("ImageTexture_ekmpw") + +[node name="List" type="ItemList" parent="."] +layout_mode = 2 +offset_top = 35.0 +offset_right = 1152.0 +offset_bottom = 648.0 +size_flags_vertical = 3 +allow_reselect = true + +[connection signal="theme_changed" from="." to="." method="_on_theme_changed"] +[connection signal="text_changed" from="FilterEdit" to="." method="_on_filter_edit_text_changed"] +[connection signal="item_clicked" from="List" to="." method="_on_list_item_clicked"] diff --git a/addons/dialogue_manager/components/update_button.gd b/addons/dialogue_manager/components/update_button.gd new file mode 100644 index 0000000..b8c2809 --- /dev/null +++ b/addons/dialogue_manager/components/update_button.gd @@ -0,0 +1,126 @@ +@tool +extends Button + +const DialogueConstants = preload("../constants.gd") +const DialogueSettings = preload("../settings.gd") + +const REMOTE_RELEASES_URL = "https://api.github.com/repos/nathanhoad/godot_dialogue_manager/releases" + + +@onready var http_request: HTTPRequest = $HTTPRequest +@onready var download_dialog: AcceptDialog = $DownloadDialog +@onready var download_update_panel = $DownloadDialog/DownloadUpdatePanel +@onready var needs_reload_dialog: AcceptDialog = $NeedsReloadDialog +@onready var update_failed_dialog: AcceptDialog = $UpdateFailedDialog +@onready var timer: Timer = $Timer + +# The main editor plugin +var editor_plugin: EditorPlugin + +var needs_reload: bool = false + +# A lambda that gets called just before refreshing the plugin. Return false to stop the reload. +var on_before_refresh: Callable = func(): return true + + +func _ready() -> void: + hide() + apply_theme() + + # Check for updates on GitHub + check_for_update() + + # Check again every few hours + timer.start(60 * 60 * 12) + + +# Convert a version number to an actually comparable number +func version_to_number(version: String) -> int: + var bits = version.split(".") + return bits[0].to_int() * 1000000 + bits[1].to_int() * 1000 + bits[2].to_int() + + +func apply_theme() -> void: + var color: Color = get_theme_color("success_color", "Editor") + + if needs_reload: + color = get_theme_color("error_color", "Editor") + icon = get_theme_icon("Reload", "EditorIcons") + add_theme_color_override("icon_normal_color", color) + add_theme_color_override("icon_focus_color", color) + add_theme_color_override("icon_hover_color", color) + + add_theme_color_override("font_color", color) + add_theme_color_override("font_focus_color", color) + add_theme_color_override("font_hover_color", color) + + +func check_for_update() -> void: + if DialogueSettings.get_user_value("check_for_updates", true): + http_request.request(REMOTE_RELEASES_URL) + + +### Signals + + +func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void: + if result != HTTPRequest.RESULT_SUCCESS: return + + var current_version: String = editor_plugin.get_version() + + # Work out the next version from the releases information on GitHub + var response = JSON.parse_string(body.get_string_from_utf8()) + if typeof(response) != TYPE_ARRAY: return + + # GitHub releases are in order of creation, not order of version + var versions = (response as Array).filter(func(release): + var version: String = release.tag_name.substr(1) + return version_to_number(version) > version_to_number(current_version) + ) + if versions.size() > 0: + download_update_panel.next_version_release = versions[0] + text = DialogueConstants.translate(&"update.available").format({ version = versions[0].tag_name.substr(1) }) + show() + + +func _on_update_button_pressed() -> void: + if needs_reload: + var will_refresh = on_before_refresh.call() + if will_refresh: + editor_plugin.get_editor_interface().restart_editor(true) + else: + var scale: float = editor_plugin.get_editor_interface().get_editor_scale() + download_dialog.min_size = Vector2(300, 250) * scale + download_dialog.popup_centered() + + +func _on_download_dialog_close_requested() -> void: + download_dialog.hide() + + +func _on_download_update_panel_updated(updated_to_version: String) -> void: + download_dialog.hide() + + needs_reload_dialog.dialog_text = DialogueConstants.translate(&"update.needs_reload") + needs_reload_dialog.ok_button_text = DialogueConstants.translate(&"update.reload_ok_button") + needs_reload_dialog.cancel_button_text = DialogueConstants.translate(&"update.reload_cancel_button") + needs_reload_dialog.popup_centered() + + needs_reload = true + text = DialogueConstants.translate(&"update.reload_project") + apply_theme() + + +func _on_download_update_panel_failed() -> void: + download_dialog.hide() + update_failed_dialog.dialog_text = DialogueConstants.translate(&"update.failed") + update_failed_dialog.popup_centered() + + +func _on_needs_reload_dialog_confirmed() -> void: + editor_plugin.get_editor_interface().restart_editor(true) + + +func _on_timer_timeout() -> void: + if not needs_reload: + check_for_update() diff --git a/addons/dialogue_manager/components/update_button.tscn b/addons/dialogue_manager/components/update_button.tscn new file mode 100644 index 0000000..533a94e --- /dev/null +++ b/addons/dialogue_manager/components/update_button.tscn @@ -0,0 +1,42 @@ +[gd_scene load_steps=3 format=3 uid="uid://co8yl23idiwbi"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/components/update_button.gd" id="1_d2tpb"] +[ext_resource type="PackedScene" uid="uid://qdxrxv3c3hxk" path="res://addons/dialogue_manager/components/download_update_panel.tscn" id="2_iwm7r"] + +[node name="UpdateButton" type="Button"] +visible = false +offset_right = 8.0 +offset_bottom = 8.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_color = Color(0, 0, 0, 1) +theme_override_colors/font_focus_color = Color(0, 0, 0, 1) +text = "v2.9.0 available" +flat = true +script = ExtResource("1_d2tpb") + +[node name="HTTPRequest" type="HTTPRequest" parent="."] + +[node name="DownloadDialog" type="AcceptDialog" parent="."] +title = "Download update" +size = Vector2i(400, 300) +unresizable = true +min_size = Vector2i(300, 250) +ok_button_text = "Close" + +[node name="DownloadUpdatePanel" parent="DownloadDialog" instance=ExtResource("2_iwm7r")] + +[node name="UpdateFailedDialog" type="AcceptDialog" parent="."] +dialog_text = "You have been updated to version 2.4.3" + +[node name="NeedsReloadDialog" type="ConfirmationDialog" parent="."] + +[node name="Timer" type="Timer" parent="."] +wait_time = 14400.0 + +[connection signal="pressed" from="." to="." method="_on_update_button_pressed"] +[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_request_completed"] +[connection signal="close_requested" from="DownloadDialog" to="." method="_on_download_dialog_close_requested"] +[connection signal="failed" from="DownloadDialog/DownloadUpdatePanel" to="." method="_on_download_update_panel_failed"] +[connection signal="updated" from="DownloadDialog/DownloadUpdatePanel" to="." method="_on_download_update_panel_updated"] +[connection signal="confirmed" from="NeedsReloadDialog" to="." method="_on_needs_reload_dialog_confirmed"] +[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"] diff --git a/addons/dialogue_manager/constants.gd b/addons/dialogue_manager/constants.gd new file mode 100644 index 0000000..bc93d21 --- /dev/null +++ b/addons/dialogue_manager/constants.gd @@ -0,0 +1,187 @@ +extends Node + + +const USER_CONFIG_PATH = "user://dialogue_manager_user_config.json" +const CACHE_PATH = "user://dialogue_manager_cache.json" + +# Token types + +const TOKEN_FUNCTION = &"function" +const TOKEN_DICTIONARY_REFERENCE = &"dictionary_reference" +const TOKEN_DICTIONARY_NESTED_REFERENCE = &"dictionary_nested_reference" +const TOKEN_GROUP = &"group" +const TOKEN_ARRAY = &"array" +const TOKEN_DICTIONARY = &"dictionary" +const TOKEN_PARENS_OPEN = &"parens_open" +const TOKEN_PARENS_CLOSE = &"parens_close" +const TOKEN_BRACKET_OPEN = &"bracket_open" +const TOKEN_BRACKET_CLOSE = &"bracket_close" +const TOKEN_BRACE_OPEN = &"brace_open" +const TOKEN_BRACE_CLOSE = &"brace_close" +const TOKEN_COLON = &"colon" +const TOKEN_COMPARISON = &"comparison" +const TOKEN_ASSIGNMENT = &"assignment" +const TOKEN_OPERATOR = &"operator" +const TOKEN_COMMA = &"comma" +const TOKEN_DOT = &"dot" +const TOKEN_CONDITION = &"condition" +const TOKEN_BOOL = &"bool" +const TOKEN_NOT = &"not" +const TOKEN_AND_OR = &"and_or" +const TOKEN_STRING = &"string" +const TOKEN_NUMBER = &"number" +const TOKEN_VARIABLE = &"variable" +const TOKEN_COMMENT = &"comment" + +const TOKEN_ERROR = &"error" + +# Line types + +const TYPE_UNKNOWN = &"unknown" +const TYPE_RESPONSE = &"response" +const TYPE_TITLE = &"title" +const TYPE_CONDITION = &"condition" +const TYPE_MUTATION = &"mutation" +const TYPE_GOTO = &"goto" +const TYPE_DIALOGUE = &"dialogue" +const TYPE_ERROR = &"error" + +const TYPE_ELSE = &"else" + +# Line IDs + +const ID_NULL = &"" +const ID_ERROR = &"error" +const ID_ERROR_INVALID_TITLE = &"invalid title" +const ID_ERROR_TITLE_HAS_NO_BODY = &"title has no body" +const ID_END = &"end" +const ID_END_CONVERSATION = &"end!" + +# Errors + +const ERR_ERRORS_IN_IMPORTED_FILE = 100 +const ERR_FILE_ALREADY_IMPORTED = 101 +const ERR_DUPLICATE_IMPORT_NAME = 102 +const ERR_EMPTY_TITLE = 103 +const ERR_DUPLICATE_TITLE = 104 +const ERR_NESTED_TITLE = 105 +const ERR_TITLE_INVALID_CHARACTERS = 106 +const ERR_UNKNOWN_TITLE = 107 +const ERR_INVALID_TITLE_REFERENCE = 108 +const ERR_TITLE_REFERENCE_HAS_NO_CONTENT = 109 +const ERR_INVALID_EXPRESSION = 110 +const ERR_UNEXPECTED_CONDITION = 111 +const ERR_DUPLICATE_ID = 112 +const ERR_MISSING_ID = 113 +const ERR_INVALID_INDENTATION = 114 +const ERR_INVALID_CONDITION_INDENTATION = 115 +const ERR_INCOMPLETE_EXPRESSION = 116 +const ERR_INVALID_EXPRESSION_FOR_VALUE = 117 +const ERR_UNKNOWN_LINE_SYNTAX = 118 +const ERR_TITLE_BEGINS_WITH_NUMBER = 119 +const ERR_UNEXPECTED_END_OF_EXPRESSION = 120 +const ERR_UNEXPECTED_FUNCTION = 121 +const ERR_UNEXPECTED_BRACKET = 122 +const ERR_UNEXPECTED_CLOSING_BRACKET = 123 +const ERR_MISSING_CLOSING_BRACKET = 124 +const ERR_UNEXPECTED_OPERATOR = 125 +const ERR_UNEXPECTED_COMMA = 126 +const ERR_UNEXPECTED_COLON = 127 +const ERR_UNEXPECTED_DOT = 128 +const ERR_UNEXPECTED_BOOLEAN = 129 +const ERR_UNEXPECTED_STRING = 130 +const ERR_UNEXPECTED_NUMBER = 131 +const ERR_UNEXPECTED_VARIABLE = 132 +const ERR_INVALID_INDEX = 133 +const ERR_UNEXPECTED_ASSIGNMENT = 134 +const ERR_UNKNOWN_USING = 135 + + +## Get the error message +static func get_error_message(error: int) -> String: + match error: + ERR_ERRORS_IN_IMPORTED_FILE: + return translate(&"errors.import_errors") + ERR_FILE_ALREADY_IMPORTED: + return translate(&"errors.already_imported") + ERR_DUPLICATE_IMPORT_NAME: + return translate(&"errors.duplicate_import") + ERR_EMPTY_TITLE: + return translate(&"errors.empty_title") + ERR_DUPLICATE_TITLE: + return translate(&"errors.duplicate_title") + ERR_NESTED_TITLE: + return translate(&"errors.nested_title") + ERR_TITLE_INVALID_CHARACTERS: + return translate(&"errors.invalid_title_string") + ERR_TITLE_BEGINS_WITH_NUMBER: + return translate(&"errors.invalid_title_number") + ERR_UNKNOWN_TITLE: + return translate(&"errors.unknown_title") + ERR_INVALID_TITLE_REFERENCE: + return translate(&"errors.jump_to_invalid_title") + ERR_TITLE_REFERENCE_HAS_NO_CONTENT: + return translate(&"errors.title_has_no_content") + ERR_INVALID_EXPRESSION: + return translate(&"errors.invalid_expression") + ERR_UNEXPECTED_CONDITION: + return translate(&"errors.unexpected_condition") + ERR_DUPLICATE_ID: + return translate(&"errors.duplicate_id") + ERR_MISSING_ID: + return translate(&"errors.missing_id") + ERR_INVALID_INDENTATION: + return translate(&"errors.invalid_indentation") + ERR_INVALID_CONDITION_INDENTATION: + return translate(&"errors.condition_has_no_content") + ERR_INCOMPLETE_EXPRESSION: + return translate(&"errors.incomplete_expression") + ERR_INVALID_EXPRESSION_FOR_VALUE: + return translate(&"errors.invalid_expression_for_value") + ERR_FILE_NOT_FOUND: + return translate(&"errors.file_not_found") + ERR_UNEXPECTED_END_OF_EXPRESSION: + return translate(&"errors.unexpected_end_of_expression") + ERR_UNEXPECTED_FUNCTION: + return translate(&"errors.unexpected_function") + ERR_UNEXPECTED_BRACKET: + return translate(&"errors.unexpected_bracket") + ERR_UNEXPECTED_CLOSING_BRACKET: + return translate(&"errors.unexpected_closing_bracket") + ERR_MISSING_CLOSING_BRACKET: + return translate(&"errors.missing_closing_bracket") + ERR_UNEXPECTED_OPERATOR: + return translate(&"errors.unexpected_operator") + ERR_UNEXPECTED_COMMA: + return translate(&"errors.unexpected_comma") + ERR_UNEXPECTED_COLON: + return translate(&"errors.unexpected_colon") + ERR_UNEXPECTED_DOT: + return translate(&"errors.unexpected_dot") + ERR_UNEXPECTED_BOOLEAN: + return translate(&"errors.unexpected_boolean") + ERR_UNEXPECTED_STRING: + return translate(&"errors.unexpected_string") + ERR_UNEXPECTED_NUMBER: + return translate(&"errors.unexpected_number") + ERR_UNEXPECTED_VARIABLE: + return translate(&"errors.unexpected_variable") + ERR_INVALID_INDEX: + return translate(&"errors.invalid_index") + ERR_UNEXPECTED_ASSIGNMENT: + return translate(&"errors.unexpected_assignment") + ERR_UNKNOWN_USING: + return translate(&"errors.unknown_using") + + return translate(&"errors.unknown") + + +static func translate(string: String) -> String: + var base_path = new().get_script().resource_path.get_base_dir() + + var language: String = TranslationServer.get_tool_locale() + var translations_path: String = "%s/l10n/%s.po" % [base_path, language] + var fallback_translations_path: String = "%s/l10n/%s.po" % [base_path, TranslationServer.get_tool_locale().substr(0, 2)] + var en_translations_path: String = "%s/l10n/en.po" % base_path + var translations: Translation = load(translations_path if FileAccess.file_exists(translations_path) else (fallback_translations_path if FileAccess.file_exists(fallback_translations_path) else en_translations_path)) + return translations.get_message(string) diff --git a/addons/dialogue_manager/dialogue_label.gd b/addons/dialogue_manager/dialogue_label.gd new file mode 100644 index 0000000..24057be --- /dev/null +++ b/addons/dialogue_manager/dialogue_label.gd @@ -0,0 +1,226 @@ +@icon("./assets/icon.svg") + +@tool + +## A RichTextLabel specifically for use with [b]Dialogue Manager[/b] dialogue. +class_name DialogueLabel extends RichTextLabel + + +## Emitted for each letter typed out. +signal spoke(letter: String, letter_index: int, speed: float) + +## Emitted when typing paused for a `[wait]` +signal paused_typing(duration: float) + +## Emitted when the player skips the typing of dialogue. +signal skipped_typing() + +## Emitted when typing finishes. +signal finished_typing() + + +# The action to press to skip typing. +@export var skip_action: StringName = &"ui_cancel" + +## The speed with which the text types out. +@export var seconds_per_step: float = 0.02 + +## Automatically have a brief pause when these characters are encountered. +@export var pause_at_characters: String = ".?!" + +## Don't auto pause if the charcter after the pause is one of these. +@export var skip_pause_at_character_if_followed_by: String = ")\"" + +## Don't auto pause after these abbreviations (only if "." is in `pause_at_characters`).[br] +## Abbreviations are limitted to 5 characters in length [br] +## Does not support multi-period abbreviations (ex. "p.m.") +@export var skip_pause_at_abbreviations: PackedStringArray = ["Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex"] + +## The amount of time to pause when exposing a character present in pause_at_characters. +@export var seconds_per_pause_step: float = 0.3 + + +## The current line of dialogue. +var dialogue_line: + set(next_dialogue_line): + dialogue_line = next_dialogue_line + custom_minimum_size = Vector2.ZERO + text = dialogue_line.text + get: + return dialogue_line + +## Whether the label is currently typing itself out. +var is_typing: bool = false: + set(value): + var is_finished: bool = is_typing != value and value == false + is_typing = value + if is_finished: + finished_typing.emit() + get: + return is_typing + +var _last_wait_index: int = -1 +var _last_mutation_index: int = -1 +var _waiting_seconds: float = 0 +var _is_awaiting_mutation: bool = false + + +func _process(delta: float) -> void: + if self.is_typing: + # Type out text + if visible_ratio < 1: + # See if we are waiting + if _waiting_seconds > 0: + _waiting_seconds = _waiting_seconds - delta + # If we are no longer waiting then keep typing + if _waiting_seconds <= 0: + _type_next(delta, _waiting_seconds) + else: + # Make sure any mutations at the end of the line get run + _mutate_inline_mutations(get_total_character_count()) + self.is_typing = false + + +func _unhandled_input(event: InputEvent) -> void: + # Note: this will no longer be reached if using Dialogue Manager > 2.32.2. To make skip handling + # simpler (so all of mouse/keyboard/joypad are together) it is now the responsibility of the + # dialogue balloon. + if self.is_typing and visible_ratio < 1 and InputMap.has_action(skip_action) and event.is_action_pressed(skip_action): + get_viewport().set_input_as_handled() + skip_typing() + + +## Start typing out the text +func type_out() -> void: + text = dialogue_line.text + visible_characters = 0 + visible_ratio = 0 + _waiting_seconds = 0 + _last_wait_index = -1 + _last_mutation_index = -1 + + self.is_typing = true + + # Allow typing listeners a chance to connect + await get_tree().process_frame + + if get_total_character_count() == 0: + self.is_typing = false + elif seconds_per_step == 0: + _mutate_remaining_mutations() + visible_characters = get_total_character_count() + self.is_typing = false + + +## Stop typing out the text and jump right to the end +func skip_typing() -> void: + _mutate_remaining_mutations() + visible_characters = get_total_character_count() + self.is_typing = false + skipped_typing.emit() + + +# Type out the next character(s) +func _type_next(delta: float, seconds_needed: float) -> void: + if _is_awaiting_mutation: return + + if visible_characters == get_total_character_count(): + return + + if _last_mutation_index != visible_characters: + _last_mutation_index = visible_characters + _mutate_inline_mutations(visible_characters) + if _is_awaiting_mutation: return + + var additional_waiting_seconds: float = _get_pause(visible_characters) + + # Pause on characters like "." + if _should_auto_pause(): + additional_waiting_seconds += seconds_per_pause_step + + # Pause at literal [wait] directives + if _last_wait_index != visible_characters and additional_waiting_seconds > 0: + _last_wait_index = visible_characters + _waiting_seconds += additional_waiting_seconds + paused_typing.emit(_get_pause(visible_characters)) + else: + visible_characters += 1 + if visible_characters <= get_total_character_count(): + spoke.emit(get_parsed_text()[visible_characters - 1], visible_characters - 1, _get_speed(visible_characters)) + # See if there's time to type out some more in this frame + seconds_needed += seconds_per_step * (1.0 / _get_speed(visible_characters)) + if seconds_needed > delta: + _waiting_seconds += seconds_needed + else: + _type_next(delta, seconds_needed) + + +# Get the pause for the current typing position if there is one +func _get_pause(at_index: int) -> float: + return dialogue_line.pauses.get(at_index, 0) + + +# Get the speed for the current typing position +func _get_speed(at_index: int) -> float: + var speed: float = 1 + for index in dialogue_line.speeds: + if index > at_index: + return speed + speed = dialogue_line.speeds[index] + return speed + + +# Run any inline mutations that haven't been run yet +func _mutate_remaining_mutations() -> void: + for i in range(visible_characters, get_total_character_count() + 1): + _mutate_inline_mutations(i) + + +# Run any mutations at the current typing position +func _mutate_inline_mutations(index: int) -> void: + for inline_mutation in dialogue_line.inline_mutations: + # inline mutations are an array of arrays in the form of [character index, resolvable function] + if inline_mutation[0] > index: + return + if inline_mutation[0] == index: + _is_awaiting_mutation = true + # The DialogueManager can't be referenced directly here so we need to get it by its path + await Engine.get_singleton("DialogueManager").mutate(inline_mutation[1], dialogue_line.extra_game_states, true) + _is_awaiting_mutation = false + + +# Determine if the current autopause character at the cursor should qualify to pause typing. +func _should_auto_pause() -> bool: + if visible_characters == 0: return false + + var parsed_text: String = get_parsed_text() + + # Avoid outofbounds when the label auto-translates and the text changes to one shorter while typing out + # Note: visible characters can be larger than parsed_text after a translation event + if visible_characters >= parsed_text.length(): return false + + # Ignore pause characters if they are next to a non-pause character + if parsed_text[visible_characters] in skip_pause_at_character_if_followed_by.split(): + return false + + # Ignore "." if it's between two numbers + if visible_characters > 3 and parsed_text[visible_characters - 1] == ".": + var possible_number: String = parsed_text.substr(visible_characters - 2, 3) + if str(float(possible_number)) == possible_number: + return false + + # Ignore "." if it's used in an abbreviation + # Note: does NOT support multi-period abbreviations (ex. p.m.) + if "." in pause_at_characters and parsed_text[visible_characters - 1] == ".": + for abbreviation in skip_pause_at_abbreviations: + if visible_characters >= abbreviation.length(): + var previous_characters: String = parsed_text.substr(visible_characters - abbreviation.length() - 1, abbreviation.length()) + if previous_characters == abbreviation: + return false + + # Ignore two non-"." characters next to each other + var other_pause_characters: PackedStringArray = pause_at_characters.replace(".", "").split() + if visible_characters > 1 and parsed_text[visible_characters - 1] in other_pause_characters and parsed_text[visible_characters] in other_pause_characters: + return false + + return parsed_text[visible_characters - 1] in pause_at_characters.split() diff --git a/addons/dialogue_manager/dialogue_label.tscn b/addons/dialogue_manager/dialogue_label.tscn new file mode 100644 index 0000000..df48b64 --- /dev/null +++ b/addons/dialogue_manager/dialogue_label.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=2 format=3 uid="uid://ckvgyvclnwggo"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_label.gd" id="1_cital"] + +[node name="DialogueLabel" type="RichTextLabel"] +anchors_preset = 10 +anchor_right = 1.0 +grow_horizontal = 2 +mouse_filter = 1 +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 = 1 +script = ExtResource("1_cital") +skip_pause_at_abbreviations = PackedStringArray("Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex") diff --git a/addons/dialogue_manager/dialogue_line.gd b/addons/dialogue_manager/dialogue_line.gd new file mode 100644 index 0000000..a9bf84a --- /dev/null +++ b/addons/dialogue_manager/dialogue_line.gd @@ -0,0 +1,98 @@ +## A line of dialogue returned from [code]DialogueManager[/code]. +class_name DialogueLine extends RefCounted + + +const _DialogueConstants = preload("./constants.gd") + + +## The ID of this line +var id: String + +## The internal type of this dialogue object. One of [code]TYPE_DIALOGUE[/code] or [code]TYPE_MUTATION[/code] +var type: String = _DialogueConstants.TYPE_DIALOGUE + +## The next line ID after this line. +var next_id: String = "" + +## The character name that is saying this line. +var character: String = "" + +## A dictionary of variable replacements fo the character name. Generally for internal use only. +var character_replacements: Array[Dictionary] = [] + +## The dialogue being spoken. +var text: String = "" + +## A dictionary of replacements for the text. Generally for internal use only. +var text_replacements: Array[Dictionary] = [] + +## The key to use for translating this line. +var translation_key: String = "" + +## A map for when and for how long to pause while typing out the dialogue text. +var pauses: Dictionary = {} + +## A map for speed changes when typing out the dialogue text. +var speeds: Dictionary = {} + +## A map of any mutations to run while typing out the dialogue text. +var inline_mutations: Array[Array] = [] + +## A list of responses attached to this line of dialogue. +var responses: Array[DialogueResponse] = [] + +## A list of any extra game states to check when resolving variables and mutations. +var extra_game_states: Array = [] + +## How long to show this line before advancing to the next. Either a float (of seconds), [code]"auto"[/code], or [code]null[/code]. +var time: String = "" + +## Any #tags that were included in the line +var tags: PackedStringArray = [] + +## The mutation details if this is a mutation line (where [code]type == TYPE_MUTATION[/code]). +var mutation: Dictionary = {} + +## The conditions to check before including this line in the flow of dialogue. If failed the line will be skipped over. +var conditions: Dictionary = {} + + +func _init(data: Dictionary = {}) -> void: + if data.size() > 0: + id = data.id + next_id = data.next_id + type = data.type + extra_game_states = data.get("extra_game_states", []) + + match type: + _DialogueConstants.TYPE_DIALOGUE: + character = data.character + character_replacements = data.get("character_replacements", [] as Array[Dictionary]) + text = data.text + text_replacements = data.get("text_replacements", [] as Array[Dictionary]) + translation_key = data.get("translation_key", data.text) + pauses = data.get("pauses", {}) + speeds = data.get("speeds", {}) + inline_mutations = data.get("inline_mutations", [] as Array[Array]) + time = data.get("time", "") + tags = data.get("tags", []) + + _DialogueConstants.TYPE_MUTATION: + mutation = data.mutation + + +func _to_string() -> String: + match type: + _DialogueConstants.TYPE_DIALOGUE: + return "<DialogueLine character=\"%s\" text=\"%s\">" % [character, text] + _DialogueConstants.TYPE_MUTATION: + return "<DialogueLine mutation>" + return "" + + +func get_tag_value(tag_name: String) -> String: + var wrapped := "%s=" % tag_name + for t in tags: + if t.begins_with(wrapped): + return t.replace(wrapped, "").strip_edges() + return "" diff --git a/addons/dialogue_manager/dialogue_manager.gd b/addons/dialogue_manager/dialogue_manager.gd new file mode 100644 index 0000000..57d7f86 --- /dev/null +++ b/addons/dialogue_manager/dialogue_manager.gd @@ -0,0 +1,1235 @@ +extends Node + + +const DialogueConstants = preload("./constants.gd") +const Builtins = preload("./utilities/builtins.gd") +const DialogueSettings = preload("./settings.gd") +const DialogueResource = preload("./dialogue_resource.gd") +const DialogueLine = preload("./dialogue_line.gd") +const DialogueResponse = preload("./dialogue_response.gd") +const DialogueManagerParser = preload("./components/parser.gd") +const DialogueManagerParseResult = preload("./components/parse_result.gd") +const ResolvedLineData = preload("./components/resolved_line_data.gd") + + +## Emitted when a title is encountered while traversing dialogue, usually when jumping from a +## goto line +signal passed_title(title: String) + +## Emitted when a line of dialogue is encountered. +signal got_dialogue(line: DialogueLine) + +## Emitted when a mutation is encountered. +signal mutated(mutation: Dictionary) + +## Emitted when some dialogue has reached the end. +signal dialogue_ended(resource: DialogueResource) + +## Used internally. +signal bridge_get_next_dialogue_line_completed(line: DialogueLine) + +## Used inernally +signal bridge_mutated() + + +enum MutationBehaviour { + Wait, + DoNotWait, + Skip +} + +enum TranslationSource { + None, + Guess, + CSV, + PO +} + + +## The list of globals that dialogue can query +var game_states: Array = [] + +## Allow dialogue to call singletons +var include_singletons: bool = true + +## Allow dialogue to call static methods/properties on classes +var include_classes: bool = true + +## Manage translation behaviour +var translation_source: TranslationSource = TranslationSource.Guess + +## Used to resolve the current scene. Override if your game manages the current scene itself. +var get_current_scene: Callable = func(): + var current_scene: Node = get_tree().current_scene + if current_scene == null: + current_scene = get_tree().root.get_child(get_tree().root.get_child_count() - 1) + return current_scene + +var _has_loaded_autoloads: bool = false +var _autoloads: Dictionary = {} + + +var _node_properties: Array = [] + + +func _ready() -> void: + # Cache the known Node2D properties + _node_properties = ["Script Variables"] + var temp_node: Node2D = Node2D.new() + for property in temp_node.get_property_list(): + _node_properties.append(property.name) + temp_node.free() + + # Make the dialogue manager available as a singleton + if Engine.has_singleton("DialogueManager"): + Engine.unregister_singleton("DialogueManager") + Engine.register_singleton("DialogueManager", self) + + # Connect up the C# signals if need be + if DialogueSettings.has_dotnet_solution(): + _get_dotnet_dialogue_manager().Prepare() + + +## Step through lines and run any mutations until we either hit some dialogue or the end of the conversation +func get_next_dialogue_line(resource: DialogueResource, key: String = "", extra_game_states: Array = [], mutation_behaviour: MutationBehaviour = MutationBehaviour.Wait) -> DialogueLine: + # You have to provide a valid dialogue resource + if resource == null: + assert(false, DialogueConstants.translate(&"runtime.no_resource")) + if resource.lines.size() == 0: + assert(false, DialogueConstants.translate(&"runtime.no_content").format({ file_path = resource.resource_path })) + + # Inject any "using" states into the game_states + for state_name in resource.using_states: + var autoload = get_tree().root.get_node_or_null(state_name) + if autoload == null: + printerr(DialogueConstants.translate(&"runtime.unknown_autoload").format({ autoload = state_name })) + else: + extra_game_states = [autoload] + extra_game_states + + # Get the line data + var dialogue: DialogueLine = await get_line(resource, key, extra_game_states) + + # If our dialogue is nothing then we hit the end + if not is_valid(dialogue): + (func(): dialogue_ended.emit(resource)).call_deferred() + return null + + # Run the mutation if it is one + if dialogue.type == DialogueConstants.TYPE_MUTATION: + var actual_next_id: String = dialogue.next_id.split(",")[0] + match mutation_behaviour: + MutationBehaviour.Wait: + await mutate(dialogue.mutation, extra_game_states) + MutationBehaviour.DoNotWait: + mutate(dialogue.mutation, extra_game_states) + MutationBehaviour.Skip: + pass + if actual_next_id in [DialogueConstants.ID_END_CONVERSATION, DialogueConstants.ID_NULL, null]: + # End the conversation + (func(): dialogue_ended.emit(resource)).call_deferred() + return null + else: + return await get_next_dialogue_line(resource, dialogue.next_id, extra_game_states, mutation_behaviour) + else: + got_dialogue.emit(dialogue) + return dialogue + + +func get_resolved_line_data(data: Dictionary, extra_game_states: Array = []) -> ResolvedLineData: + var text: String = translate(data) + + # Resolve variables + for replacement in data.text_replacements: + var value = await resolve(replacement.expression.duplicate(true), extra_game_states) + var index: int = text.find(replacement.value_in_text) + text = text.substr(0, index) + str(value) + text.substr(index + replacement.value_in_text.length()) + + var parser: DialogueManagerParser = DialogueManagerParser.new() + + # Resolve random groups + for found in parser.INLINE_RANDOM_REGEX.search_all(text): + var options = found.get_string(&"options").split(&"|") + text = text.replace(&"[[%s]]" % found.get_string(&"options"), options[randi_range(0, options.size() - 1)]) + + # Do a pass on the markers to find any conditionals + var markers: ResolvedLineData = parser.extract_markers(text) + + # Resolve any conditionals and update marker positions as needed + if data.type == DialogueConstants.TYPE_DIALOGUE: + var resolved_text: String = markers.text + var conditionals: Array[RegExMatch] = parser.INLINE_CONDITIONALS_REGEX.search_all(resolved_text) + var replacements: Array = [] + for conditional in conditionals: + var condition_raw: String = conditional.strings[conditional.names.condition] + var body: String = conditional.strings[conditional.names.body] + var body_else: String = "" + if &"[else]" in body: + var bits = body.split(&"[else]") + body = bits[0] + body_else = bits[1] + var condition: Dictionary = parser.extract_condition("if " + condition_raw, false, 0) + # If the condition fails then use the else of "" + if not await check_condition({ condition = condition }, extra_game_states): + body = body_else + replacements.append({ + start = conditional.get_start(), + end = conditional.get_end(), + string = conditional.get_string(), + body = body + }) + + for i in range(replacements.size() -1, -1, -1): + var r: Dictionary = replacements[i] + resolved_text = resolved_text.substr(0, r.start) + r.body + resolved_text.substr(r.end, 9999) + # Move any other markers now that the text has changed + var offset: int = r.end - r.start - r.body.length() + for key in [&"pauses", &"speeds", &"time"]: + if markers.get(key) == null: continue + var marker = markers.get(key) + var next_marker: Dictionary = {} + for index in marker: + if index < r.start: + next_marker[index] = marker[index] + elif index > r.start: + next_marker[index - offset] = marker[index] + markers.set(key, next_marker) + var mutations: Array[Array] = markers.mutations + var next_mutations: Array[Array] = [] + for mutation in mutations: + var index = mutation[0] + if index < r.start: + next_mutations.append(mutation) + elif index > r.start: + next_mutations.append([index - offset, mutation[1]]) + markers.mutations = next_mutations + + markers.text = resolved_text + + parser.free() + + return markers + + +## Replace any variables, etc in the character name +func get_resolved_character(data: Dictionary, extra_game_states: Array = []) -> String: + var character: String = data.get(&"character", "") + + # Resolve variables + for replacement in data.get(&"character_replacements", []): + var value = await resolve(replacement.expression.duplicate(true), extra_game_states) + var index: int = character.find(replacement.value_in_text) + character = character.substr(0, index) + str(value) + character.substr(index + replacement.value_in_text.length()) + + # Resolve random groups + var random_regex: RegEx = RegEx.new() + random_regex.compile("\\[\\[(?<options>.*?)\\]\\]") + for found in random_regex.search_all(character): + var options = found.get_string(&"options").split("|") + character = character.replace("[[%s]]" % found.get_string(&"options"), options[randi_range(0, options.size() - 1)]) + + return character + + +## Generate a dialogue resource on the fly from some text +func create_resource_from_text(text: String) -> Resource: + var parser: DialogueManagerParser = DialogueManagerParser.new() + parser.parse(text, "") + var results: DialogueManagerParseResult = parser.get_data() + var errors: Array[Dictionary] = parser.get_errors() + parser.free() + + if errors.size() > 0: + printerr(DialogueConstants.translate(&"runtime.errors").format({ count = errors.size() })) + for error in errors: + printerr(DialogueConstants.translate(&"runtime.error_detail").format({ + line = error.line_number + 1, + message = DialogueConstants.get_error_message(error.error) + })) + assert(false, DialogueConstants.translate(&"runtime.errors_see_details").format({ count = errors.size() })) + + var resource: DialogueResource = DialogueResource.new() + resource.using_states = results.using_states + resource.titles = results.titles + resource.first_title = results.first_title + resource.character_names = results.character_names + resource.lines = results.lines + resource.raw_text = text + + return resource + + +## Show the example balloon +func show_example_dialogue_balloon(resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> CanvasLayer: + var balloon: Node = load(_get_example_balloon_path()).instantiate() + get_current_scene.call().add_child(balloon) + balloon.start(resource, title, extra_game_states) + + return balloon + + +## Show the configured dialogue balloon +func show_dialogue_balloon(resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> Node: + var balloon_path: String = DialogueSettings.get_setting(&"balloon_path", _get_example_balloon_path()) + if not ResourceLoader.exists(balloon_path): + balloon_path = _get_example_balloon_path() + return show_dialogue_balloon_scene(balloon_path, resource, title, extra_game_states) + + +## Show a given balloon scene +func show_dialogue_balloon_scene(balloon_scene, resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> Node: + if balloon_scene is String: + balloon_scene = load(balloon_scene) + if balloon_scene is PackedScene: + balloon_scene = balloon_scene.instantiate() + + var balloon: Node = balloon_scene + get_current_scene.call().add_child(balloon) + if balloon.has_method(&"start"): + balloon.start(resource, title, extra_game_states) + elif balloon.has_method(&"Start"): + balloon.Start(resource, title, extra_game_states) + else: + assert(false, DialogueConstants.translate(&"runtime.dialogue_balloon_missing_start_method")) + return balloon + + +# Get the path to the example balloon +func _get_example_balloon_path() -> String: + var is_small_window: bool = ProjectSettings.get_setting("display/window/size/viewport_width") < 400 + var balloon_path: String = "/example_balloon/small_example_balloon.tscn" if is_small_window else "/example_balloon/example_balloon.tscn" + return get_script().resource_path.get_base_dir() + balloon_path + + +### Dotnet bridge + + +func _get_dotnet_dialogue_manager() -> Node: + return load(get_script().resource_path.get_base_dir() + "/DialogueManager.cs").new() + + +func _bridge_get_next_dialogue_line(resource: DialogueResource, key: String, extra_game_states: Array = []) -> void: + # dotnet needs at least one await tick of the signal gets called too quickly + await get_tree().process_frame + + var line = await get_next_dialogue_line(resource, key, extra_game_states) + bridge_get_next_dialogue_line_completed.emit(line) + + +func _bridge_mutate(mutation: Dictionary, extra_game_states: Array, is_inline_mutation: bool = false) -> void: + await mutate(mutation, extra_game_states, is_inline_mutation) + bridge_mutated.emit() + + +### Helpers + + +# Get a line by its ID +func get_line(resource: DialogueResource, key: String, extra_game_states: Array) -> DialogueLine: + key = key.strip_edges() + + # See if we were given a stack instead of just the one key + var stack: Array = key.split("|") + key = stack.pop_front() + var id_trail: String = "" if stack.size() == 0 else "|" + "|".join(stack) + + # Key is blank so just use the first title + if key == null or key == "": + key = resource.first_title + + # See if we just ended the conversation + if key in [DialogueConstants.ID_END, DialogueConstants.ID_NULL, null]: + if stack.size() > 0: + return await get_line(resource, "|".join(stack), extra_game_states) + else: + return null + elif key == DialogueConstants.ID_END_CONVERSATION: + return null + + # See if it is a title + if key.begins_with("~ "): + key = key.substr(2) + if resource.titles.has(key): + key = resource.titles.get(key) + + if key in resource.titles.values(): + passed_title.emit(resource.titles.find_key(key)) + + if not resource.lines.has(key): + assert(false, DialogueConstants.translate(&"errors.key_not_found").format({ key = key })) + + var data: Dictionary = resource.lines.get(key) + + # Check for weighted random lines + if data.has(&"siblings"): + var target_weight: float = randf_range(0, data.siblings.reduce(func(total, sibling): return total + sibling.weight, 0)) + var cummulative_weight: float = 0 + for sibling in data.siblings: + if target_weight < cummulative_weight + sibling.weight: + data = resource.lines.get(sibling.id) + break + else: + cummulative_weight += sibling.weight + + # Check condtiions + if data.type == DialogueConstants.TYPE_CONDITION: + # "else" will have no actual condition + if await check_condition(data, extra_game_states): + return await get_line(resource, data.next_id + id_trail, extra_game_states) + else: + return await get_line(resource, data.next_conditional_id + id_trail, extra_game_states) + + # Evaluate jumps + elif data.type == DialogueConstants.TYPE_GOTO: + if data.is_snippet: + id_trail = "|" + data.next_id_after + id_trail + return await get_line(resource, data.next_id + id_trail, extra_game_states) + + elif data.type == DialogueConstants.TYPE_DIALOGUE: + if not data.has(&"id"): + data.id = key + + # Set up a line object + var line: DialogueLine = await create_dialogue_line(data, extra_game_states) + + # If the jump point somehow has no content then just end + if not line: return null + + # If we are the first of a list of responses then get the other ones + if data.type == DialogueConstants.TYPE_RESPONSE: + # Note: For some reason C# has occasional issues with using the responses property directly + # so instead we use set and get here. + line.set(&"responses", await get_responses(data.get(&"responses", []), resource, id_trail, extra_game_states)) + return line + + # Inject the next node's responses if they have any + if resource.lines.has(line.next_id): + var next_line: Dictionary = resource.lines.get(line.next_id) + + # If the response line is marked as a title then make sure to emit the passed_title signal. + if line.next_id in resource.titles.values(): + passed_title.emit(resource.titles.find_key(line.next_id)) + + # If the next line is a title then check where it points to see if that is a set of responses. + if next_line.type == DialogueConstants.TYPE_GOTO and resource.lines.has(next_line.next_id): + next_line = resource.lines.get(next_line.next_id) + + if next_line != null and next_line.type == DialogueConstants.TYPE_RESPONSE: + # Note: For some reason C# has occasional issues with using the responses property directly + # so instead we use set and get here. + line.set(&"responses", await get_responses(next_line.get(&"responses", []), resource, id_trail, extra_game_states)) + + line.next_id = "|".join(stack) if line.next_id == DialogueConstants.ID_NULL else line.next_id + id_trail + return line + + +# Show a message or crash with error +func show_error_for_missing_state_value(message: String, will_show: bool = true) -> void: + if not will_show: return + + if DialogueSettings.get_setting(&"ignore_missing_state_values", false): + push_error(message) + elif will_show: + # If you're here then you're missing a method or property in your game state. The error + # message down in the debugger will give you some more information. + assert(false, message) + + +# Translate a string +func translate(data: Dictionary) -> String: + if translation_source == TranslationSource.None: + return data.text + + if data.translation_key == "" or data.translation_key == data.text: + return tr(data.text) + else: + # Line IDs work slightly differently depending on whether the translation came from a + # CSV or a PO file. CSVs use the line ID (or the line itself) as the translatable string + # whereas POs use the ID as context and the line itself as the translatable string. + match translation_source: + TranslationSource.PO: + return tr(data.text, StringName(data.translation_key)) + + TranslationSource.CSV: + return tr(data.translation_key) + + TranslationSource.Guess: + var translation_files: Array = ProjectSettings.get_setting(&"internationalization/locale/translations") + if translation_files.filter(func(f: String): return f.get_extension() == &"po").size() > 0: + # Assume PO + return tr(data.text, StringName(data.translation_key)) + else: + # Assume CSV + return tr(data.translation_key) + + return tr(data.translation_key) + + +# Create a line of dialogue +func create_dialogue_line(data: Dictionary, extra_game_states: Array) -> DialogueLine: + match data.type: + DialogueConstants.TYPE_DIALOGUE: + var resolved_data: ResolvedLineData = await get_resolved_line_data(data, extra_game_states) + return DialogueLine.new({ + id = data.get(&"id", ""), + type = DialogueConstants.TYPE_DIALOGUE, + next_id = data.next_id, + character = await get_resolved_character(data, extra_game_states), + character_replacements = data.character_replacements, + text = resolved_data.text, + text_replacements = data.text_replacements, + translation_key = data.translation_key, + pauses = resolved_data.pauses, + speeds = resolved_data.speeds, + inline_mutations = resolved_data.mutations, + time = resolved_data.time, + tags = data.get(&"tags", []), + extra_game_states = extra_game_states + }) + + DialogueConstants.TYPE_RESPONSE: + return DialogueLine.new({ + id = data.get(&"id", ""), + type = DialogueConstants.TYPE_RESPONSE, + next_id = data.next_id, + tags = data.get(&"tags", []), + extra_game_states = extra_game_states + }) + + DialogueConstants.TYPE_MUTATION: + return DialogueLine.new({ + id = data.get(&"id", ""), + type = DialogueConstants.TYPE_MUTATION, + next_id = data.next_id, + mutation = data.mutation, + extra_game_states = extra_game_states + }) + + return null + + +# Create a response +func create_response(data: Dictionary, extra_game_states: Array) -> DialogueResponse: + var resolved_data: ResolvedLineData = await get_resolved_line_data(data, extra_game_states) + return DialogueResponse.new({ + id = data.get(&"id", ""), + type = DialogueConstants.TYPE_RESPONSE, + next_id = data.next_id, + is_allowed = data.is_allowed, + character = await get_resolved_character(data, extra_game_states), + character_replacements = data.get(&"character_replacements", [] as Array[Dictionary]), + text = resolved_data.text, + text_replacements = data.text_replacements, + tags = data.get(&"tags", []), + translation_key = data.translation_key + }) + + +# Get the current game states +func get_game_states(extra_game_states: Array) -> Array: + if not _has_loaded_autoloads: + _has_loaded_autoloads = true + # Add any autoloads to a generic state so we can refer to them by name + for child in get_tree().root.get_children(): + # Ignore the dialogue manager + if child.name == &"DialogueManager": continue + # Ignore the current main scene + if get_tree().current_scene and child.name == get_tree().current_scene.name: continue + # Add the node to our known autoloads + _autoloads[child.name] = child + game_states = [_autoloads] + # Add any other state shortcuts from settings + for node_name in DialogueSettings.get_setting(&"states", []): + var state: Node = get_node_or_null("/root/" + node_name) + if state: + game_states.append(state) + + var current_scene: Node = get_current_scene.call() + var unique_states: Array = [] + for state in extra_game_states + [current_scene] + game_states: + if state != null and not unique_states.has(state): + unique_states.append(state) + return unique_states + + +# Check if a condition is met +func check_condition(data: Dictionary, extra_game_states: Array) -> bool: + if data.get(&"condition", null) == null: return true + if data.condition.size() == 0: return true + + return await resolve(data.condition.expression.duplicate(true), extra_game_states) + + +# Make a change to game state or run a method +func mutate(mutation: Dictionary, extra_game_states: Array, is_inline_mutation: bool = false) -> void: + var expression: Array[Dictionary] = mutation.expression + + # Handle built in mutations + if expression[0].type == DialogueConstants.TOKEN_FUNCTION and expression[0].function in [&"wait", &"debug"]: + var args: Array = await resolve_each(expression[0].value, extra_game_states) + match expression[0].function: + &"wait": + mutated.emit(mutation) + await get_tree().create_timer(float(args[0])).timeout + return + + &"debug": + prints("Debug:", args) + await get_tree().process_frame + + # Or pass through to the resolver + else: + if not mutation_contains_assignment(mutation.expression) and not is_inline_mutation: + mutated.emit(mutation) + + if mutation.get("is_blocking", true): + await resolve(mutation.expression.duplicate(true), extra_game_states) + return + else: + resolve(mutation.expression.duplicate(true), extra_game_states) + + # Wait one frame to give the dialogue handler a chance to yield + await get_tree().process_frame + + +func mutation_contains_assignment(mutation: Array) -> bool: + for token in mutation: + if token.type == DialogueConstants.TOKEN_ASSIGNMENT: + return true + return false + + +func resolve_each(array: Array, extra_game_states: Array) -> Array: + var results: Array = [] + for item in array: + results.append(await resolve(item.duplicate(true), extra_game_states)) + return results + + +# Replace an array of line IDs with their response prompts +func get_responses(ids: Array, resource: DialogueResource, id_trail: String, extra_game_states: Array) -> Array[DialogueResponse]: + var responses: Array[DialogueResponse] = [] + for id in ids: + var data: Dictionary = resource.lines.get(id).duplicate(true) + data.is_allowed = await check_condition(data, extra_game_states) + if DialogueSettings.get_setting(&"include_all_responses", false) or data.is_allowed: + var response: DialogueResponse = await create_response(data, extra_game_states) + response.next_id += id_trail + responses.append(response) + + return responses + + +# Get a value on the current scene or game state +func get_state_value(property: String, extra_game_states: Array): + # Special case for static primitive calls + if property == "Color": + return Color() + elif property == "Vector2": + return Vector2.ZERO + elif property == "Vector3": + return Vector3.ZERO + elif property == "Vector4": + return Vector4.ZERO + elif property == "Quaternian": + return Quaternion() + + var expression = Expression.new() + if expression.parse(property) != OK: + assert(false, DialogueConstants.translate(&"runtime.invalid_expression").format({ expression = property, error = expression.get_error_text() })) + + for state in get_game_states(extra_game_states): + if typeof(state) == TYPE_DICTIONARY: + if state.has(property): + return state.get(property) + else: + var result = expression.execute([], state, false) + if not expression.has_execute_failed(): + return result + + if include_singletons and Engine.has_singleton(property): + return Engine.get_singleton(property) + + if include_classes: + for class_data in ProjectSettings.get_global_class_list(): + if class_data.get(&"class") == property: + return load(class_data.path).new() + + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found").format({ property = property, states = str(get_game_states(extra_game_states)) })) + + +# Set a value on the current scene or game state +func set_state_value(property: String, value, extra_game_states: Array) -> void: + for state in get_game_states(extra_game_states): + if typeof(state) == TYPE_DICTIONARY: + if state.has(property): + state[property] = value + return + elif thing_has_property(state, property): + state.set(property, value) + return + + if property.to_snake_case() != property: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found_missing_export").format({ property = property, states = str(get_game_states(extra_game_states)) })) + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found").format({ property = property, states = str(get_game_states(extra_game_states)) })) + + +# Collapse any expressions +func resolve(tokens: Array, extra_game_states: Array): + # Handle groups first + for token in tokens: + if token.type == DialogueConstants.TOKEN_GROUP: + token["type"] = "value" + token["value"] = await resolve(token.value, extra_game_states) + + # Then variables/methods + var i: int = 0 + var limit: int = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + + if token.type == DialogueConstants.TOKEN_FUNCTION: + var function_name: String = token.function + var args = await resolve_each(token.value, extra_game_states) + if tokens[i - 1].type == DialogueConstants.TOKEN_DOT: + # If we are calling a deeper function then we need to collapse the + # value into the thing we are calling the function on + var caller: Dictionary = tokens[i - 2] + if Builtins.is_supported(caller.value): + caller["type"] = "value" + caller["value"] = Builtins.resolve_method(caller.value, function_name, args) + tokens.remove_at(i) + tokens.remove_at(i-1) + i -= 2 + elif thing_has_method(caller.value, function_name, args): + caller["type"] = "value" + caller["value"] = await resolve_thing_method(caller.value, function_name, args) + tokens.remove_at(i) + tokens.remove_at(i-1) + i -= 2 + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.method_not_callable").format({ method = function_name, object = str(caller.value) })) + else: + var found: bool = false + match function_name: + &"str": + token["type"] = "value" + token["value"] = str(args[0]) + found = true + &"Vector2": + token["type"] = "value" + token["value"] = Vector2(args[0], args[1]) + found = true + &"Vector2i": + token["type"] = "value" + token["value"] = Vector2i(args[0], args[1]) + found = true + &"Vector3": + token["type"] = "value" + token["value"] = Vector3(args[0], args[1], args[2]) + found = true + &"Vector3i": + token["type"] = "value" + token["value"] = Vector3i(args[0], args[1], args[2]) + found = true + &"Vector4": + token["type"] = "value" + token["value"] = Vector4(args[0], args[1], args[2], args[3]) + found = true + &"Vector4i": + token["type"] = "value" + token["value"] = Vector4i(args[0], args[1], args[2], args[3]) + found = true + &"Quaternion": + token["type"] = "value" + token["value"] = Quaternion(args[0], args[1], args[2], args[3]) + found = true + &"Color": + token["type"] = "value" + match args.size(): + 0: + token["value"] = Color() + 1: + token["value"] = Color(args[0]) + 2: + token["value"] = Color(args[0], args[1]) + 3: + token["value"] = Color(args[0], args[1], args[2]) + 4: + token["value"] = Color(args[0], args[1], args[2], args[3]) + found = true + &"load": + token["type"] = "value" + token["value"] = load(args[0]) + found = true + &"emit": + token["type"] = "value" + token["value"] = resolve_signal(args, extra_game_states) + found = true + _: + for state in get_game_states(extra_game_states): + if thing_has_method(state, function_name, args): + token["type"] = "value" + token["value"] = await resolve_thing_method(state, function_name, args) + found = true + break + + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.method_not_found").format({ + method = args[0] if function_name in ["call", "call_deferred"] else function_name, + states = str(get_game_states(extra_game_states)) + }), not found) + + elif token.type == DialogueConstants.TOKEN_DICTIONARY_REFERENCE: + var value + if i > 0 and tokens[i - 1].type == DialogueConstants.TOKEN_DOT: + # If we are deep referencing then we need to get the parent object. + # `parent.value` is the actual object and `token.variable` is the name of + # the property within it. + value = tokens[i - 2].value[token.variable] + # Clean up the previous tokens + token.erase("variable") + tokens.remove_at(i - 1) + tokens.remove_at(i - 2) + i -= 2 + else: + # Otherwise we can just get this variable as a normal state reference + value = get_state_value(token.variable, extra_game_states) + + var index = await resolve(token.value, extra_game_states) + if typeof(value) == TYPE_DICTIONARY: + if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # If the next token is an assignment then we need to leave this as a reference + # so that it can be resolved once everything ahead of it has been resolved + token["type"] = "dictionary" + token["value"] = value + token["key"] = index + else: + if value.has(index): + token["type"] = "value" + token["value"] = value[index] + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.key_not_found").format({ key = str(index), dictionary = token.variable })) + elif typeof(value) == TYPE_ARRAY: + if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # If the next token is an assignment then we need to leave this as a reference + # so that it can be resolved once everything ahead of it has been resolved + token["type"] = "array" + token["value"] = value + token["key"] = index + else: + if index >= 0 and index < value.size(): + token["type"] = "value" + token["value"] = value[index] + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = index, array = token.variable })) + + elif token.type == DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE: + var dictionary: Dictionary = tokens[i - 1] + var index = await resolve(token.value, extra_game_states) + var value = dictionary.value + if typeof(value) == TYPE_DICTIONARY: + if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # If the next token is an assignment then we need to leave this as a reference + # so that it can be resolved once everything ahead of it has been resolved + dictionary["type"] = "dictionary" + dictionary["key"] = index + dictionary["value"] = value + tokens.remove_at(i) + i -= 1 + else: + if dictionary.value.has(index): + dictionary["value"] = value.get(index) + tokens.remove_at(i) + i -= 1 + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.key_not_found").format({ key = str(index), dictionary = value })) + elif typeof(value) == TYPE_ARRAY: + if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # If the next token is an assignment then we need to leave this as a reference + # so that it can be resolved once everything ahead of it has been resolved + dictionary["type"] = "array" + dictionary["value"] = value + dictionary["key"] = index + tokens.remove_at(i) + i -= 1 + else: + if index >= 0 and index < value.size(): + dictionary["value"] = value[index] + tokens.remove_at(i) + i -= 1 + else: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = index, array = value })) + + elif token.type == DialogueConstants.TOKEN_ARRAY: + token["type"] = "value" + token["value"] = await resolve_each(token.value, extra_game_states) + + elif token.type == DialogueConstants.TOKEN_DICTIONARY: + token["type"] = "value" + var dictionary = {} + for key in token.value.keys(): + var resolved_key = await resolve([key], extra_game_states) + var preresolved_value = token.value.get(key) + if typeof(preresolved_value) != TYPE_ARRAY: + preresolved_value = [preresolved_value] + var resolved_value = await resolve(preresolved_value, extra_game_states) + dictionary[resolved_key] = resolved_value + token["value"] = dictionary + + elif token.type == DialogueConstants.TOKEN_VARIABLE or token.type == DialogueConstants.TOKEN_NUMBER: + if str(token.value) == "null": + token["type"] = "value" + token["value"] = null + elif tokens[i - 1].type == DialogueConstants.TOKEN_DOT: + var caller: Dictionary = tokens[i - 2] + var property = token.value + if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # If the next token is an assignment then we need to leave this as a reference + # so that it can be resolved once everything ahead of it has been resolved + caller["type"] = "property" + caller["property"] = property + else: + # If we are requesting a deeper property then we need to collapse the + # value into the thing we are referencing from + caller["type"] = "value" + if Builtins.is_supported(caller.value): + caller["value"] = Builtins.resolve_property(caller.value, property) + else: + caller["value"] = caller.value.get(property) + tokens.remove_at(i) + tokens.remove_at(i-1) + i -= 2 + elif tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: + # It's a normal variable but we will be assigning to it so don't resolve + # it until everything after it has been resolved + token["type"] = "variable" + else: + token["type"] = "value" + token["value"] = get_state_value(str(token.value), extra_game_states) + + i += 1 + + # Then multiply and divide + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_OPERATOR and token.value in ["*", "/", "%"]: + token["type"] = "value" + token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) + tokens.remove_at(i+1) + tokens.remove_at(i-1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + # Then addition and subtraction + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_OPERATOR and token.value in ["+", "-"]: + token["type"] = "value" + token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) + tokens.remove_at(i+1) + tokens.remove_at(i-1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + # Then negations + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_NOT: + token["type"] = "value" + token["value"] = not tokens[i+1].value + tokens.remove_at(i+1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + # Then comparisons + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_COMPARISON: + token["type"] = "value" + token["value"] = compare(token.value, tokens[i-1].value, tokens[i+1].value) + tokens.remove_at(i+1) + tokens.remove_at(i-1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + # Then and/or + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_AND_OR: + token["type"] = "value" + token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) + tokens.remove_at(i+1) + tokens.remove_at(i-1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + # Lastly, resolve any assignments + i = 0 + limit = 0 + while i < tokens.size() and limit < 1000: + limit += 1 + var token: Dictionary = tokens[i] + if token.type == DialogueConstants.TOKEN_ASSIGNMENT: + var lhs: Dictionary = tokens[i - 1] + var value + + match lhs.type: + &"variable": + value = apply_operation(token.value, get_state_value(lhs.value, extra_game_states), tokens[i+1].value) + set_state_value(lhs.value, value, extra_game_states) + &"property": + value = apply_operation(token.value, lhs.value.get(lhs.property), tokens[i+1].value) + if typeof(lhs.value) == TYPE_DICTIONARY: + lhs.value[lhs.property] = value + else: + lhs.value.set(lhs.property, value) + &"dictionary": + value = apply_operation(token.value, lhs.value.get(lhs.key, null), tokens[i+1].value) + lhs.value[lhs.key] = value + &"array": + show_error_for_missing_state_value( + DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = lhs.key, array = lhs.value }), + lhs.key >= lhs.value.size() + ) + value = apply_operation(token.value, lhs.value[lhs.key], tokens[i+1].value) + lhs.value[lhs.key] = value + _: + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.left_hand_size_cannot_be_assigned_to")) + + token["type"] = "value" + token["value"] = value + tokens.remove_at(i+1) + tokens.remove_at(i-1) + i -= 1 + i += 1 + + if limit >= 1000: + assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) + + return tokens[0].value + + +func compare(operator: String, first_value, second_value) -> bool: + match operator: + &"in": + if first_value == null or second_value == null: + return false + else: + return first_value in second_value + &"<": + if first_value == null: + return true + elif second_value == null: + return false + else: + return first_value < second_value + &">": + if first_value == null: + return false + elif second_value == null: + return true + else: + return first_value > second_value + &"<=": + if first_value == null: + return true + elif second_value == null: + return false + else: + return first_value <= second_value + &">=": + if first_value == null: + return false + elif second_value == null: + return true + else: + return first_value >= second_value + &"==": + if first_value == null: + if typeof(second_value) == TYPE_BOOL: + return second_value == false + else: + return second_value == null + else: + return first_value == second_value + &"!=": + if first_value == null: + if typeof(second_value) == TYPE_BOOL: + return second_value == true + else: + return second_value != null + else: + return first_value != second_value + + return false + + +func apply_operation(operator: String, first_value, second_value): + match operator: + &"=": + return second_value + &"+", &"+=": + return first_value + second_value + &"-", &"-=": + return first_value - second_value + &"/", &"/=": + return first_value / second_value + &"*", &"*=": + return first_value * second_value + &"%": + return first_value % second_value + &"and": + return first_value and second_value + &"or": + return first_value or second_value + + assert(false, DialogueConstants.translate(&"runtime.unknown_operator")) + + +# Check if a dialogue line contains meaningful information +func is_valid(line: DialogueLine) -> bool: + if line == null: + return false + if line.type == DialogueConstants.TYPE_MUTATION and line.mutation == null: + return false + if line.type == DialogueConstants.TYPE_RESPONSE and line.get(&"responses").size() == 0: + return false + return true + + +func thing_has_method(thing, method: String, args: Array) -> bool: + if Builtins.is_supported(thing): + return thing != _autoloads + + if method in [&"call", &"call_deferred"]: + return thing.has_method(args[0]) + + if method == &"emit_signal": + return thing.has_signal(args[0]) + + if thing.has_method(method): + return true + + if method.to_snake_case() != method and DialogueSettings.has_dotnet_solution(): + # If we get this far then the method might be a C# method with a Task return type + return _get_dotnet_dialogue_manager().ThingHasMethod(thing, method) + + return false + + +# Check if a given property exists +func thing_has_property(thing: Object, property: String) -> bool: + if thing == null: + return false + + for p in thing.get_property_list(): + if _node_properties.has(p.name): + # Ignore any properties on the base Node + continue + if p.name == property: + return true + + return false + + +func resolve_signal(args: Array, extra_game_states: Array): + if args[0] is Signal: + args[0] = args[0].get_name() + + for state in get_game_states(extra_game_states): + if typeof(state) == TYPE_DICTIONARY: + continue + elif state.has_signal(args[0]): + match args.size(): + 1: + state.emit_signal(args[0]) + 2: + state.emit_signal(args[0], args[1]) + 3: + state.emit_signal(args[0], args[1], args[2]) + 4: + state.emit_signal(args[0], args[1], args[2], args[3]) + 5: + state.emit_signal(args[0], args[1], args[2], args[3], args[4]) + 6: + state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5]) + 7: + state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5], args[6]) + 8: + state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]) + return + + # The signal hasn't been found anywhere + show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.signal_not_found").format({ signal_name = args[0], states = str(get_game_states(extra_game_states)) })) + + +func resolve_thing_method(thing, method: String, args: Array): + if Builtins.is_supported(thing): + var result = Builtins.resolve_method(thing, method, args) + if not Builtins.has_resolve_method_failed(): + return result + + if thing.has_method(method): + # Try to convert any literals to the right type + var method_info: Dictionary = thing.get_method_list().filter(func(m): return method == m.name)[0] + var method_args: Array = method_info.args + if method_info.flags & METHOD_FLAG_VARARG == 0 and method_args.size() < args.size(): + assert(false, DialogueConstants.translate(&"runtime.expected_n_got_n_args").format({ expected = method_args.size(), method = method, received = args.size()})) + for i in range(0, args.size()): + var m: Dictionary = method_args[i] + var to_type:int = typeof(args[i]) + if m.type == TYPE_ARRAY: + match m.hint_string: + &"String": + to_type = TYPE_PACKED_STRING_ARRAY + &"int": + to_type = TYPE_PACKED_INT64_ARRAY + &"float": + to_type = TYPE_PACKED_FLOAT64_ARRAY + &"Vector2": + to_type = TYPE_PACKED_VECTOR2_ARRAY + &"Vector3": + to_type = TYPE_PACKED_VECTOR3_ARRAY + _: + if m.hint_string != "": + assert(false, DialogueConstants.translate(&"runtime.unsupported_array_type").format({ type = m.hint_string})) + if typeof(args[i]) != to_type: + args[i] = convert(args[i], to_type) + + return await thing.callv(method, args) + + # If we get here then it's probably a C# method with a Task return type + var dotnet_dialogue_manager = _get_dotnet_dialogue_manager() + dotnet_dialogue_manager.ResolveThingMethod(thing, method, args) + return await dotnet_dialogue_manager.Resolved diff --git a/addons/dialogue_manager/dialogue_reponses_menu.gd b/addons/dialogue_manager/dialogue_reponses_menu.gd new file mode 100644 index 0000000..6da0e5c --- /dev/null +++ b/addons/dialogue_manager/dialogue_reponses_menu.gd @@ -0,0 +1,131 @@ +@icon("./assets/responses_menu.svg") + +## A VBoxContainer for dialogue responses provided by [b]Dialogue Manager[/b]. +class_name DialogueResponsesMenu extends VBoxContainer + + +## Emitted when a response is selected. +signal response_selected(response) + + +## Optionally specify a control to duplicate for each response +@export var response_template: Control + +## The action for accepting a response (is possibly overridden by parent dialogue balloon). +@export var next_action: StringName = &"" + +# The list of dialogue responses. +var responses: Array = []: + set(value): + responses = value + + # Remove any current items + for item in get_children(): + if item == response_template: continue + + remove_child(item) + item.queue_free() + + # Add new items + if responses.size() > 0: + for response in responses: + var item: Control + if is_instance_valid(response_template): + item = response_template.duplicate(DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_SIGNALS) + item.show() + else: + item = Button.new() + item.name = "Response%d" % get_child_count() + if not response.is_allowed: + item.name = String(item.name) + "Disallowed" + item.disabled = true + + # If the item has a response property then use that + if "response" in item: + item.response = response + # Otherwise assume we can just set the text + else: + item.text = response.text + + item.set_meta("response", response) + + add_child(item) + + _configure_focus() + + +func _ready() -> void: + visibility_changed.connect(func(): + if visible and get_menu_items().size() > 0: + get_menu_items()[0].grab_focus() + ) + + if is_instance_valid(response_template): + response_template.hide() + + +# This is deprecated. +func set_responses(next_responses: Array) -> void: + self.responses = next_responses + + +# Prepare the menu for keyboard and mouse navigation. +func _configure_focus() -> void: + var items = get_menu_items() + for i in items.size(): + var item: Control = items[i] + + item.focus_mode = Control.FOCUS_ALL + + item.focus_neighbor_left = item.get_path() + item.focus_neighbor_right = item.get_path() + + if i == 0: + item.focus_neighbor_top = item.get_path() + item.focus_previous = item.get_path() + else: + item.focus_neighbor_top = items[i - 1].get_path() + item.focus_previous = items[i - 1].get_path() + + if i == items.size() - 1: + item.focus_neighbor_bottom = item.get_path() + item.focus_next = item.get_path() + else: + item.focus_neighbor_bottom = items[i + 1].get_path() + item.focus_next = items[i + 1].get_path() + + item.mouse_entered.connect(_on_response_mouse_entered.bind(item)) + item.gui_input.connect(_on_response_gui_input.bind(item, item.get_meta("response"))) + + items[0].grab_focus() + + +## Get the selectable items in the menu. +func get_menu_items() -> Array: + var items: Array = [] + for child in get_children(): + if not child.visible: continue + if "Disallowed" in child.name: continue + items.append(child) + + return items + + +### Signals + + +func _on_response_mouse_entered(item: Control) -> void: + if "Disallowed" in item.name: return + + item.grab_focus() + + +func _on_response_gui_input(event: InputEvent, item: Control, response) -> void: + if "Disallowed" in item.name: return + + get_viewport().set_input_as_handled() + + if event is InputEventMouseButton and event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT: + response_selected.emit(response) + elif event.is_action_pressed(&"ui_accept" if next_action.is_empty() else next_action) and item in get_menu_items(): + response_selected.emit(response) diff --git a/addons/dialogue_manager/dialogue_resource.gd b/addons/dialogue_manager/dialogue_resource.gd new file mode 100644 index 0000000..a406560 --- /dev/null +++ b/addons/dialogue_manager/dialogue_resource.gd @@ -0,0 +1,42 @@ +@tool +@icon("./assets/icon.svg") + +## A collection of dialogue lines for use with [code]DialogueManager[/code]. +class_name DialogueResource extends Resource + + +const _DialogueManager = preload("./dialogue_manager.gd") + +## A list of state shortcuts +@export var using_states: PackedStringArray = [] + +## A map of titles and the lines they point to. +@export var titles: Dictionary = {} + +## A list of character names. +@export var character_names: PackedStringArray = [] + +## The first title in the file. +@export var first_title: String = "" + +## A map of the encoded lines of dialogue. +@export var lines: Dictionary = {} + +## raw version of the text +@export var raw_text: String + + +## Get the next printable line of dialogue, starting from a referenced line ([code]title[/code] can +## be a title string or a stringified line number). Runs any mutations along the way and then returns +## the first dialogue line encountered. +func get_next_dialogue_line(title: String, extra_game_states: Array = [], mutation_behaviour: _DialogueManager.MutationBehaviour = _DialogueManager.MutationBehaviour.Wait) -> DialogueLine: + return await Engine.get_singleton("DialogueManager").get_next_dialogue_line(self, title, extra_game_states, mutation_behaviour) + + +## Get the list of any titles found in the file. +func get_titles() -> PackedStringArray: + return titles.keys() + + +func _to_string() -> String: + return "<DialogueResource titles=\"%s\">" % [",".join(titles.keys())] diff --git a/addons/dialogue_manager/dialogue_response.gd b/addons/dialogue_manager/dialogue_response.gd new file mode 100644 index 0000000..92cec24 --- /dev/null +++ b/addons/dialogue_manager/dialogue_response.gd @@ -0,0 +1,62 @@ +## A response to a line of dialogue, usualy attached to a [code]DialogueLine[/code]. +class_name DialogueResponse extends RefCounted + + +const _DialogueConstants = preload("./constants.gd") + + +## The ID of this response +var id: String + +## The internal type of this dialogue object, always set to [code]TYPE_RESPONSE[/code]. +var type: String = _DialogueConstants.TYPE_RESPONSE + +## The next line ID to use if this response is selected by the player. +var next_id: String = "" + +## [code]true[/code] if the condition of this line was met. +var is_allowed: bool = true + +## A character (depending on the "characters in responses" behaviour setting). +var character: String = "" + +## A dictionary of varialbe replaces for the character name. Generally for internal use only. +var character_replacements: Array[Dictionary] = [] + +## The prompt for this response. +var text: String = "" + +## A dictionary of variable replaces for the text. Generally for internal use only. +var text_replacements: Array[Dictionary] = [] + +## Any #tags +var tags: PackedStringArray = [] + +## The key to use for translating the text. +var translation_key: String = "" + + +func _init(data: Dictionary = {}) -> void: + if data.size() > 0: + id = data.id + type = data.type + next_id = data.next_id + is_allowed = data.is_allowed + character = data.character + character_replacements = data.character_replacements + text = data.text + text_replacements = data.text_replacements + tags = data.tags + translation_key = data.translation_key + + +func _to_string() -> String: + return "<DialogueResponse text=\"%s\">" % text + + +func get_tag_value(tag_name: String) -> String: + var wrapped := "%s=" % tag_name + for t in tags: + if t.begins_with(wrapped): + return t.replace(wrapped, "").strip_edges() + return "" diff --git a/addons/dialogue_manager/editor_translation_parser_plugin.gd b/addons/dialogue_manager/editor_translation_parser_plugin.gd new file mode 100644 index 0000000..9d404e2 --- /dev/null +++ b/addons/dialogue_manager/editor_translation_parser_plugin.gd @@ -0,0 +1,43 @@ +extends EditorTranslationParserPlugin + + +const DialogueConstants = preload("./constants.gd") +const DialogueSettings = preload("./settings.gd") +const DialogueManagerParseResult = preload("./components/parse_result.gd") + + +func _parse_file(path: String, msgids: Array, msgids_context_plural: Array) -> void: + var file: FileAccess = FileAccess.open(path, FileAccess.READ) + var text: String = file.get_as_text() + + var data: DialogueManagerParseResult = DialogueManagerParser.parse_string(text, path) + var known_keys: PackedStringArray = PackedStringArray([]) + + # Add all character names if settings ask for it + if DialogueSettings.get_setting("export_characters_in_translation", true): + var character_names: PackedStringArray = data.character_names + for character_name in character_names: + if character_name in known_keys: continue + + known_keys.append(character_name) + + msgids_context_plural.append([character_name.replace('"', '\\"'), "dialogue", ""]) + + # Add all dialogue lines and responses + var dialogue: Dictionary = data.lines + for key in dialogue.keys(): + var line: Dictionary = dialogue.get(key) + + if not line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: continue + if line.translation_key in known_keys: continue + + known_keys.append(line.translation_key) + + if line.translation_key == "" or line.translation_key == line.text: + msgids_context_plural.append([line.text.replace('"', '\\"'), "", ""]) + else: + msgids_context_plural.append([line.text.replace('"', '\\"'), line.translation_key.replace('"', '\\"'), ""]) + + +func _get_recognized_extensions() -> PackedStringArray: + return ["dialogue"] diff --git a/addons/dialogue_manager/example_balloon/ExampleBalloon.cs b/addons/dialogue_manager/example_balloon/ExampleBalloon.cs new file mode 100644 index 0000000..a6574e0 --- /dev/null +++ b/addons/dialogue_manager/example_balloon/ExampleBalloon.cs @@ -0,0 +1,204 @@ +using Godot; +using Godot.Collections; + +namespace DialogueManagerRuntime +{ + public partial class ExampleBalloon : CanvasLayer + { + [Export] public string NextAction = "ui_accept"; + [Export] public string SkipAction = "ui_cancel"; + + + Control balloon; + RichTextLabel characterLabel; + RichTextLabel dialogueLabel; + VBoxContainer responsesMenu; + + Resource resource; + Array<Variant> temporaryGameStates = new Array<Variant>(); + bool isWaitingForInput = false; + bool willHideBalloon = false; + + DialogueLine dialogueLine; + DialogueLine DialogueLine + { + get => dialogueLine; + set + { + isWaitingForInput = false; + balloon.FocusMode = Control.FocusModeEnum.All; + balloon.GrabFocus(); + + if (value == null) + { + QueueFree(); + return; + } + + dialogueLine = value; + UpdateDialogue(); + } + } + + + public override void _Ready() + { + balloon = GetNode<Control>("%Balloon"); + characterLabel = GetNode<RichTextLabel>("%CharacterLabel"); + dialogueLabel = GetNode<RichTextLabel>("%DialogueLabel"); + responsesMenu = GetNode<VBoxContainer>("%ResponsesMenu"); + + balloon.Hide(); + + balloon.GuiInput += (@event) => + { + if ((bool)dialogueLabel.Get("is_typing")) + { + bool mouseWasClicked = @event is InputEventMouseButton && (@event as InputEventMouseButton).ButtonIndex == MouseButton.Left && @event.IsPressed(); + bool skipButtonWasPressed = @event.IsActionPressed(SkipAction); + if (mouseWasClicked || skipButtonWasPressed) + { + GetViewport().SetInputAsHandled(); + dialogueLabel.Call("skip_typing"); + return; + } + } + + if (!isWaitingForInput) return; + if (dialogueLine.Responses.Count > 0) return; + + GetViewport().SetInputAsHandled(); + + if (@event is InputEventMouseButton && @event.IsPressed() && (@event as InputEventMouseButton).ButtonIndex == MouseButton.Left) + { + Next(dialogueLine.NextId); + } + else if (@event.IsActionPressed(NextAction) && GetViewport().GuiGetFocusOwner() == balloon) + { + Next(dialogueLine.NextId); + } + }; + + if (string.IsNullOrEmpty((string)responsesMenu.Get("next_action"))) + { + responsesMenu.Set("next_action", NextAction); + } + responsesMenu.Connect("response_selected", Callable.From((DialogueResponse response) => + { + Next(response.NextId); + })); + + DialogueManager.Mutated += OnMutated; + } + + + public override void _ExitTree() + { + DialogueManager.Mutated -= OnMutated; + } + + + public override void _UnhandledInput(InputEvent @event) + { + // Only the balloon is allowed to handle input while it's showing + GetViewport().SetInputAsHandled(); + } + + + public async void Start(Resource dialogueResource, string title, Array<Variant> extraGameStates = null) + { + temporaryGameStates = extraGameStates ?? new Array<Variant>(); + isWaitingForInput = false; + resource = dialogueResource; + + DialogueLine = await DialogueManager.GetNextDialogueLine(resource, title, temporaryGameStates); + } + + + public async void Next(string nextId) + { + DialogueLine = await DialogueManager.GetNextDialogueLine(resource, nextId, temporaryGameStates); + } + + + #region Helpers + + + private async void UpdateDialogue() + { + if (!IsNodeReady()) + { + await ToSignal(this, SignalName.Ready); + } + + // Set up the character name + characterLabel.Visible = !string.IsNullOrEmpty(dialogueLine.Character); + characterLabel.Text = Tr(dialogueLine.Character, "dialogue"); + + // Set up the dialogue + dialogueLabel.Hide(); + dialogueLabel.Set("dialogue_line", dialogueLine); + + // Set up the responses + responsesMenu.Hide(); + responsesMenu.Set("responses", dialogueLine.Responses); + + // Type out the text + balloon.Show(); + willHideBalloon = false; + dialogueLabel.Show(); + if (!string.IsNullOrEmpty(dialogueLine.Text)) + { + dialogueLabel.Call("type_out"); + await ToSignal(dialogueLabel, "finished_typing"); + } + + // Wait for input + if (dialogueLine.Responses.Count > 0) + { + balloon.FocusMode = Control.FocusModeEnum.None; + responsesMenu.Show(); + } + else if (!string.IsNullOrEmpty(dialogueLine.Time)) + { + float time = 0f; + if (!float.TryParse(dialogueLine.Time, out time)) + { + time = dialogueLine.Text.Length * 0.02f; + } + await ToSignal(GetTree().CreateTimer(time), "timeout"); + Next(dialogueLine.NextId); + } + else + { + isWaitingForInput = true; + balloon.FocusMode = Control.FocusModeEnum.All; + balloon.GrabFocus(); + } + } + + + #endregion + + + #region signals + + + private void OnMutated(Dictionary _mutation) + { + isWaitingForInput = false; + willHideBalloon = true; + GetTree().CreateTimer(0.1f).Timeout += () => + { + if (willHideBalloon) + { + willHideBalloon = false; + balloon.Hide(); + } + }; + } + + + #endregion + } +} \ No newline at end of file diff --git a/addons/dialogue_manager/example_balloon/example_balloon.gd b/addons/dialogue_manager/example_balloon/example_balloon.gd new file mode 100644 index 0000000..875e52f --- /dev/null +++ b/addons/dialogue_manager/example_balloon/example_balloon.gd @@ -0,0 +1,141 @@ +extends CanvasLayer + +## 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" + +@onready var balloon: Control = %Balloon +@onready var character_label: RichTextLabel = %CharacterLabel +@onready var dialogue_label: DialogueLabel = %DialogueLabel +@onready var responses_menu: DialogueResponsesMenu = %ResponsesMenu + +## 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 + +## The current line +var dialogue_line: DialogueLine: + set(next_dialogue_line): + is_waiting_for_input = false + balloon.focus_mode = Control.FOCUS_ALL + balloon.grab_focus() + + # The dialogue has finished so close the balloon + if not next_dialogue_line: + queue_free() + return + + # If the node isn't ready yet then none of the labels will be ready yet either + if not is_node_ready(): + await ready + + dialogue_line = next_dialogue_line + + 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.set_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() + get: + return dialogue_line + + +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 + + +func _unhandled_input(_event: InputEvent) -> void: + # Only the balloon is allowed to handle input while it's showing + get_viewport().set_input_as_handled() + + +## 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) + + +## 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) + + +### Signals + + +func _on_mutated(_mutation: Dictionary) -> void: + is_waiting_for_input = false + will_hide_balloon = true + get_tree().create_timer(0.1).timeout.connect(func(): + if will_hide_balloon: + will_hide_balloon = false + balloon.hide() + ) + + +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 _on_responses_menu_response_selected(response: DialogueResponse) -> void: + next(response.next_id) diff --git a/addons/dialogue_manager/example_balloon/example_balloon.tscn b/addons/dialogue_manager/example_balloon/example_balloon.tscn new file mode 100644 index 0000000..6facc26 --- /dev/null +++ b/addons/dialogue_manager/example_balloon/example_balloon.tscn @@ -0,0 +1,149 @@ +[gd_scene load_steps=9 format=3 uid="uid://73jm5qjy52vq"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/example_balloon/example_balloon.gd" id="1_36de5"] +[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_a8ve6"] +[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_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="ExampleBalloon" type="CanvasLayer"] +layer = 100 +script = ExtResource("1_36de5") + +[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="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("2_a8ve6")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +text = "Dialogue..." + +[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" + +[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"] diff --git a/addons/dialogue_manager/example_balloon/small_example_balloon.tscn b/addons/dialogue_manager/example_balloon/small_example_balloon.tscn new file mode 100644 index 0000000..3011833 --- /dev/null +++ b/addons/dialogue_manager/example_balloon/small_example_balloon.tscn @@ -0,0 +1,173 @@ +[gd_scene load_steps=10 format=3 uid="uid://13s5spsk34qu"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/example_balloon/example_balloon.gd" id="1_s2gbs"] +[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_hfvdi"] +[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_menu.gd" id="3_1j1j0"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_235ry"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.345098, 0.345098, 0.345098, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ufjut"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.227451, 0.227451, 0.227451, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(1, 1, 1, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fcbqo"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_t6i7a"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uy0d5"] +bg_color = Color(0, 0, 0, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="Theme" id="Theme_qq3yp"] +default_font_size = 8 +Button/styles/disabled = SubResource("StyleBoxFlat_235ry") +Button/styles/focus = SubResource("StyleBoxFlat_ufjut") +Button/styles/hover = SubResource("StyleBoxFlat_fcbqo") +Button/styles/normal = SubResource("StyleBoxFlat_t6i7a") +MarginContainer/constants/margin_bottom = 4 +MarginContainer/constants/margin_left = 8 +MarginContainer/constants/margin_right = 8 +MarginContainer/constants/margin_top = 4 +Panel/styles/panel = SubResource("StyleBoxFlat_uy0d5") + +[node name="ExampleBalloon" type="CanvasLayer"] +layer = 100 +script = ExtResource("1_s2gbs") + +[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"] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 3.0 +offset_top = -62.0 +offset_right = -4.0 +offset_bottom = -4.0 +grow_horizontal = 2 +grow_vertical = 0 + +[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="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("2_hfvdi")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +text = "Dialogue..." +skip_pause_at_abbreviations = PackedStringArray("Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex") + +[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 = -124.0 +offset_top = -218.0 +offset_right = 125.0 +offset_bottom = -50.0 +grow_horizontal = 2 +grow_vertical = 0 + +[node name="ResponsesMenu" type="VBoxContainer" parent="Balloon/Responses"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 8 +theme_override_constants/separation = 2 +script = ExtResource("3_1j1j0") + +[node name="ResponseExample" type="Button" parent="Balloon/Responses/ResponsesMenu"] +layout_mode = 2 +text = "Response Example" + +[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"] diff --git a/addons/dialogue_manager/import_plugin.gd b/addons/dialogue_manager/import_plugin.gd new file mode 100644 index 0000000..3f0af15 --- /dev/null +++ b/addons/dialogue_manager/import_plugin.gd @@ -0,0 +1,113 @@ +@tool +extends EditorImportPlugin + + +signal compiled_resource(resource: Resource) + + +const DialogueResource = preload("./dialogue_resource.gd") +const DialogueManagerParseResult = preload("./components/parse_result.gd") + +const compiler_version = 11 + + +func _get_importer_name() -> String: + # NOTE: A change to this forces a re-import of all dialogue + return "dialogue_manager_compiler_%s" % compiler_version + + +func _get_visible_name() -> String: + return "Dialogue" + + +func _get_import_order() -> int: + return -1000 + + +func _get_priority() -> float: + return 1000.0 + + +func _get_resource_type(): + return "Resource" + + +func _get_recognized_extensions() -> PackedStringArray: + return PackedStringArray(["dialogue"]) + + +func _get_save_extension(): + return "tres" + + +func _get_preset_count() -> int: + return 0 + + +func _get_preset_name(preset_index: int) -> String: + return "Unknown" + + +func _get_import_options(path: String, preset_index: int) -> Array: + # When the options array is empty there is a misleading error on export + # that actually means nothing so let's just have an invisible option. + return [{ + name = "defaults", + default_value = true + }] + + +func _get_option_visibility(path: String, option_name: StringName, options: Dictionary) -> bool: + return false + + +func _import(source_file: String, save_path: String, options: Dictionary, platform_variants: Array[String], gen_files: Array[String]) -> Error: + var cache = Engine.get_meta("DialogueCache") + + # Get the raw file contents + if not FileAccess.file_exists(source_file): return ERR_FILE_NOT_FOUND + + var file: FileAccess = FileAccess.open(source_file, FileAccess.READ) + var raw_text: String = file.get_as_text() + + # Parse the text + var parser: DialogueManagerParser = DialogueManagerParser.new() + var err: Error = parser.parse(raw_text, source_file) + var data: DialogueManagerParseResult = parser.get_data() + var errors: Array[Dictionary] = parser.get_errors() + parser.free() + + if err != OK: + printerr("%d errors found in %s" % [errors.size(), source_file]) + cache.add_errors_to_file(source_file, errors) + return err + + # Get the current addon version + var config: ConfigFile = ConfigFile.new() + config.load("res://addons/dialogue_manager/plugin.cfg") + var version: String = config.get_value("plugin", "version") + + # Save the results to a resource + var resource: DialogueResource = DialogueResource.new() + resource.set_meta("dialogue_manager_version", version) + + resource.using_states = data.using_states + resource.titles = data.titles + resource.first_title = data.first_title + resource.character_names = data.character_names + resource.lines = data.lines + resource.raw_text = data.raw_text + + # Clear errors and possibly trigger any cascade recompiles + cache.add_file(source_file, data) + + err = ResourceSaver.save(resource, "%s.%s" % [save_path, _get_save_extension()]) + + compiled_resource.emit(resource) + + # Recompile any dependencies + var dependent_paths: PackedStringArray = cache.get_dependent_paths_for_reimport(source_file) + for path in dependent_paths: + append_import_external_resource(path) + + return err diff --git a/addons/dialogue_manager/l10n/en.mo b/addons/dialogue_manager/l10n/en.mo new file mode 100644 index 0000000000000000000000000000000000000000..2ab4fdfdac7d7f52d3d107052e417714a09b6bdc GIT binary patch literal 9770 zcmb7|e~=|tRmU654>HjZFn|zEZYJRF#>`8yQCViQEZLdeWZ3Kvc4m`+N~h;_&rE0D z>wa|io7u@YBoHBGiKz+{1qJ^S!Lm$QT1xy;VkL@2Sx~i>f5Z~8fI_eo3$c`xTG7w< z{&=t7>_B1HJMY`~++XLOd(OG{^jBVe*+(OuC!n8%mM)8;-v>YR3jTN=x;lz}6imQt z!2<jV@KNwJ;KxCJ(KGyA1O5^CdhiS2kAYtY)$ZTGSA$nF7*j-V0AB~*2;K<38T@hZ z0nc9tUrYIMQ2jmuYMkE&uLGY4CGQKM=KBxuX7H6v`Udb$Q0-2G*MnV;kAmv=Nnigg zC^^0e-T;0Bd=+>Zi;+C91=ar+Q2kDTny>3|2fT^$$3TtqhaNA2>i18e<i7lsPQL3w z$#)c#9^d85wJ$&E%by168a)SU9T!3A{~tlg_dSnS!BqKr5LPq;UI88f)qft;Iu?EX zsxNPXY)SNMzWgyzdj2g?<NT@Te+lFleT_d<9R0iJYf`P_I#B&?12yk4P<mJZC3gZ| z1#W<v?=evN`jD@G29%u7gBtIzJ$@UM-d@4rw}Ll-(&tG~dRqngMUU~P^?d|X|4)Oe ze-6}s{hcqr2pY<-qVb!+gB~9QHUE1-+1sy!lJip_B1FIA%g=$*%a=g4{|d;E(YHZ< zcCnK8Iu@;Vw}5h?Sy1E5fd)JeO3n@Njo?$D^zjFv`oG}o|J9eTf{95+H-eIT2Ba!l z1f}OSQ1<v3sC9n=)IR+lsD1l0Q2j50lJ_5c{dax+|AJcgwfw1mAE@@TpaJg%wZ0tG zygQ)w;lrTje+FcT=<}fT@@4RfmqpP(gO^kOE{(MRFM`s;%MnuTt^*YZZU(2o{h;Q* z6V!T6fLDSKfm+WRsP;pUp`%B@JHV$v`Tg^r|4nc|<(ELow~xWJA4kD`;2BW;H$6TH z{uJe>L9Oq3Q1ZP1PJ`bB?*gaTv|GS?K=rRc?ccA0Ocgx?N-uxu%U=f%Q~n=N?GI5Y zJ)ZH{1^Gpr{7Ek#@%S_-eSQ{{++PGG-`|6h@4rFm=~|3i<(om35Bc&*Q2ibPwT=OJ z7x*Z61pE_F`us0Y^Ipl|iodT1<-czMrT4diYIiRvJ3jBr?*?Tb>%P1N%3nSRs@;b@ z|C6Bh{WGBK;CDU$Sx|cT3sC+37L@$o@c1Gq`L8AzOOES7wYwR-4ZIDMK4Y*0Zh$Ai zr$O1nzkmn98(7qx;5$I^KL8#AKMOKN^c|3<(KW{DWya$=DE<E?DE)j6{8{iKsQy>r ztiq$9^m_r+I8T7ukKX`g&wmWcUOx{?FMkDUJ%0mgJzoZ;$8UN5e}Y=~OQ70cgYl{T z>%gA@Zv=l1JPH0h_&#ty_^ijTf{#<4!WnJ{p9D4k=RmeP`g8Ck_*L*>a0cVmd>{At z8BlioEU36~5tMvi^Y|T5_V5y@bzV&{Qhx(V54VGo^C-wKTIcW0;8URX_Y0t1H>mdC z^7uUvk)kVpI*MKf>XCg&X6@qzNRQPC_?QYjk2|n3XrJ`F4SGAI`91)xK@1;lLbApC zAnEWukRAi=KpT+OJb-FQ&wC;HLj|os;gJr{Ko3CggMJA*0O|Q4^eEI<!9Of3`Vr_M z=-rTXAD(-8xyu*s4opyb{uOBGdD~zH{Q~q>=ocY9=ONj)9_^L%xC+TW2^02_uQbp+ z^n~SH`ga%>ValFEggYB2<RkY$%g`)z3-lUD&pITZn1gPG-U7WJ3XlBmGAM=Q8+w+Y z%OTmwBaj~1sh&mXgne_iRq&2`TKn<r=(K<7dVC|;gB0Um4jqSPptI0Bp<|Hz=M?k~ zsDxyH3s3^x4^2aQI*@E%&rt_9)=c^L2R**aqd>kFLpih$+JfYl=b&GPM$htaWhJXR z-CkK|QM(W)z1}3FY}T?WUdek|J*p@NTb2_Kl4dP%>ttgzmfquJ)S+H0H{-l;qioep z){nYnv65H)*oiPv>ZEzyO{#RVO~;O(mfbqas;aE&PSUHgB;AVh{-CUyEDd}HOY<f# zi+C-m<D!gVG+EJv`gAzx<=v#o;(XMn#j~Sb+P2A?UKZF{f6#2j6D(<n$(nej92TQ- zooum_IP}hoZrLC7G9<_@463ZI5q4a;k@WKPhpJ(&DyI2xBv@X!-g%L-;zU~5J+P`S z>}J}f#Ko|`oK<_*)lHQbtD)}UVSf-eC7bHzn^47iwsol{dU=6K6lvUNy~*lG;(pHZ zi&bj~!sROIu4kjo3f1GSDl!Zxom9RPfA8%c7AQIEs!zgHt3|(M3$4oKvg~EaNL}rk zNs(GLvfe#}Znr3V<1Lur_xnlE<^<mx?;dq&IZ{ijM}|(zl|AgG)n;W_blbMjs+!#M zRz*3;s-!7L=FqB|w1rm1MpEU;^4L#?#d=Y0wsdNX6MLt)P<N|*5Y`rN=FM8XJj{D( zWW!F}%j>4YYlCgBW`)GcU}8^sT1Vc+R;rR{Qg1|gQD;@-p_ABk)5>x?$q=JW(v76( zW`URHNv~YRhkP3;bT?1-9_lNsn7JgtXk5>0vJ0b`@#{g!tf5=ImaJ#-@^ZIKM?50o zpvP)P<2XO^f;3wL8P^~gjz{sldXQny-L<5^lYH|{1zkUWA(JQ~_OKwzXGs-TSr@za zf!y+mjF&Q1W4pzPZ5vg?qRIPNC#kB0SgYU>m%~QmFDug3qZT&E#c9?gd2f=rt4$r( zS>_v#t3oJgg~TxTWIzerUbfN@;@Pb_e<X{$Nult&tb<2xt{72{<mhM3TAA9g)a8t` zMj8fc)w$puDq3epi^ay4!wUNeyg?;j;XoLN|4=1ClHOhwrDoOkZfaXLtCHXvdU>~r zHLP{PaYa2GxYI6n8{%Yd^&B@yb8GuawMER;>i2B*o+0*E6*?|`D|dMJdfrxS5lbTo z(y&(4mz!C3c*nrHYn^`5bl2DithII=LT?k^Ip{X>a#)9Qm0|j5(Kq!)djZ+SQa}jJ znsRlOgLbmBJqNAt)mhV^R88VutjG7tBpq|wYr$`89FWzwx^#zigM;Ii4WWsEGw#cF zmQ@yqQ>o^N&D;sx>d*P!8>U&jf+JvsArQ1$g#H-z_u<CahE(TQQDmFQ<ATMQYp-9U zHs}{C)c&N|N;2&6y2lEv$n~z_Ju@85qai(?`&-p?hfPb?%_<qh9Br#U4%#c8x4npN z2$IB-S|L2Lf{bFS4RZBFSZ~@JF&w0*wUcb1KkKNTk#dx1D`QuVcCp#_z;c=orM!+u zV_8!P1BC_!!L(+dteyB#DP>r)T$k`XW@>&yO*iXtMl}tG`($0YzBivB@i4cL(7GOW zyIh2#vyMHpkj~tXcVURLX5Jr2=2TK}Q>v!Uo|!p^^Qd-a9@Wg6sr!<;nOX8$D=W(> zR);j7S;~@rt2}GcZ0gj)spI1b?&#b;HRmqHGfP_o#*_2hhCk-TVI%**0*;(tIx%x- z+)i_mG|U|5_L`#WS#xMPZ>G-nhE>v=IZ;;qde#&JTda>9JZ#+Sk^P0a>4>@Gz~QL} zXYO&Qx8yxrX57-vot=Z7gHzF*%|z_KQ3~STZ0=#~B_Nt3>9DWHTK%H34gHy<?sPiQ zA}NN+3v&W<TXZRgt#wCaZJN^T+g8t=eMh5tpJ23GMDt25)ExnAVqrpJ(TVOhqol&< z+&9)@Oj0nVF4|e@*vps@Vl<s-X)UkK!o1->3|AI(a7)q{ooGHJB7P=QBpkGK&8n>3 zF)`L-jN+ha){-VPR7z4Cckr3z%-FP~;}*e8#-3(jz=T0v9wI$)_SB;VTD^9n1(%m# zU}k&>ccSB?97RI;V_L24)xXu0`6^@6k#TJ+5t(FOK(1Z#uOgRSV`AK`wB5v%MQ=;n z!1V$}_6D5%!+uufU2CxJa6-YU?^|o#$g7*1<Q|j+RLoYEVE4^QZ#CPAPG(zXdYf>( zGi_R$JFZOApzv+&*v_qHyIb~#{bFa<Z2Mrj6P<DyjPc2U@fnPt-<k{a`;f1>7v|dw z({${eOKa4L>D+#k&mfFlGd9*C9Bk3hS+v_gt;I|qd8;{odVabSogbw-ctuEcCfGj7 zndG_jW`cLgT3SP+g0h%wU6Rb~;`lUXf=dE3QRb#?%9WM{P1J^@Wr7(Dqa{zcB~7$* zDar&ZBqw6pJjB#nSQCaA%H9~>Sq{ybLd)1)wz%;bm!@=xF&9vO*0<Ki3*J<1nPe5i z>_qCU=pZ{=p<y`n!eGl8UXmFGl;aw1c6zVOs`Y*150@+-@_e++Tx?mGucHO~al(~D zWK-f}<`(Z)6kKq*&)q)hxtnaqgls3AD$#MY9;AxiF8837U3zrRrZ#r`Iuz`^>Rd=> z7L~=AW5?!{#Vn1|mnHjkgtJ5*<`NcPu$hWC+UNmk)py>uxx|hPV7n=sq_;!V=h|po zQsQ-Rx|}SZQAWc`h1kB%23Ac{Vn*W)8;$9b6TR7sGTv=*2RFG-5!`un+mE$#cH41s zlAfKgV}u*KLqTWuuyh;!!#6jJS!T`*n*q`(Ou96QAT_-`j<p0IB837%qBxqTE!RL& zYmPg6$1272@r9q&jte`}(S4*!tc{JY^E8|Exz_m+5+@8og1LO4EmTOIjH@ChGgG;& ziw(2v)nnW+DYmSU8+WNR`?uZ8&H*}VAMMvfX4@6^B1~YU`jC4Wu2UN<C6$~Z|7uGb zcoOmZ&#c}dMZ^Ev132~%?j9|MEY2v4Gd7DGhm&z&n&VC*&j=cdb<#7N70w%IUKjfs zGfLk&(GTj>-s}Hg$8o-gt?io8-KTmz?|b2T<T5{d>97|mA8c&3j<+`RlyX2!iX8B? zlE1Sd>pSPuJ&*R57v6Q~&qkreqRkzxm)O{|7;-wonZ2QNAt4_bANyW1JfM|E_%+Pg zTn?A5(XDbhv%e1u$KsQ4YK|dj2#ia#SyYn)(c*eOFeT~K=-9Tl>Ml1SF6@`160A7< z7%EE-5QuEz2h)A}soizPWh3J&WF0MW!E8ojx20A_$l>khh!$4tNuj&jP+uCY^Kj+4 zq>DX<2uJpYqkB(QD0NDafc;#{dILMq3PIQUgWoq@HgpszkjWU5l!Xv|5JRWJR>pyS zI@=sOpd3}pVo;mqxfO=g)P~0BY(l<H!a_ExL3}pa+Jh+1I)<~V;rqRU(X{+%QMq)d z<}D7+J8fkn8uwD}aqJo&!p!t!6RC)ER3G+a915Ue>GmG2)!BnKBYBZHdBbJUeX+?| zih`mGQf{~Swk2&?J(hMtb#OOxE21IQ@Y(PKB*8{Wus<;u-N%_r61a$t=z?o4s<cOz zY;B}eUD$Q%+cQ|k(fTN{v5gv)`0bcc4oj-y5@F*~&runnbvC*LViPM$v{KBVZ$irJ z>;r3ZId<fePV**i_OuTvw>zW!G&gBPjifm5Qy&z`UDTz_?y|#INDlFyZbqZg&uN2w lCarTVtC5u*F#70OVIy|S{K&hD!7oD^?9RqbGge6_`aihw)SUnT literal 0 HcmV?d00001 diff --git a/addons/dialogue_manager/l10n/en.po b/addons/dialogue_manager/l10n/en.po new file mode 100644 index 0000000..bf844cb --- /dev/null +++ b/addons/dialogue_manager/l10n/en.po @@ -0,0 +1,481 @@ +msgid "" +msgstr "" +"Project-Id-Version: Dialogue Manager\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.2.2\n" + +msgid "start_a_new_file" +msgstr "Start a new file" + +msgid "open_a_file" +msgstr "Open a file" + +msgid "open.open" +msgstr "Open..." + +msgid "open.no_recent_files" +msgstr "No recent files" + +msgid "open.clear_recent_files" +msgstr "Clear recent files" + +msgid "save_all_files" +msgstr "Save all files" + +msgid "find_in_files" +msgstr "Find in files..." + +msgid "test_dialogue" +msgstr "Test dialogue" + +msgid "search_for_text" +msgstr "Search for text" + +msgid "insert" +msgstr "Insert" + +msgid "translations" +msgstr "Translations" + +msgid "settings" +msgstr "Settings" + +msgid "sponsor" +msgstr "Sponsor" + +msgid "show_support" +msgstr "Support Dialogue Manager" + +msgid "docs" +msgstr "Docs" + +msgid "insert.wave_bbcode" +msgstr "Wave BBCode" + +msgid "insert.shake_bbcode" +msgstr "Shake BBCode" + +msgid "insert.typing_pause" +msgstr "Typing pause" + +msgid "insert.typing_speed_change" +msgstr "Typing speed change" + +msgid "insert.auto_advance" +msgstr "Auto advance" + +msgid "insert.templates" +msgstr "Templates" + +msgid "insert.title" +msgstr "Title" + +msgid "insert.dialogue" +msgstr "Dialogue" + +msgid "insert.response" +msgstr "Response" + +msgid "insert.random_lines" +msgstr "Random lines" + +msgid "insert.random_text" +msgstr "Random text" + +msgid "insert.actions" +msgstr "Actions" + +msgid "insert.jump" +msgstr "Jump to title" + +msgid "insert.end_dialogue" +msgstr "End dialogue" + +msgid "generate_line_ids" +msgstr "Generate line IDs" + +msgid "save_characters_to_csv" +msgstr "Save character names to CSV..." + +msgid "save_to_csv" +msgstr "Save lines to CSV..." + +msgid "import_from_csv" +msgstr "Import line changes from CSV..." + +msgid "confirm_close" +msgstr "Save changes to '{path}'?" + +msgid "confirm_close.save" +msgstr "Save changes" + +msgid "confirm_close.discard" +msgstr "Discard" + +msgid "buffer.save" +msgstr "Save" + +msgid "buffer.save_as" +msgstr "Save as..." + +msgid "buffer.close" +msgstr "Close" + +msgid "buffer.close_all" +msgstr "Close all" + +msgid "buffer.close_other_files" +msgstr "Close other files" + +msgid "buffer.copy_file_path" +msgstr "Copy file path" + +msgid "buffer.show_in_filesystem" +msgstr "Show in FileSystem" + +msgid "settings.invalid_test_scene" +msgstr "\"{path}\" does not extend BaseDialogueTestScene." + +msgid "settings.revert_to_default_test_scene" +msgstr "Revert to default test scene" + +msgid "settings.default_balloon_hint" +msgstr "Custom balloon to use when calling \"DialogueManager.show_balloon()\"" + +msgid "settings.revert_to_default_balloon" +msgstr "Revert to default balloon" + +msgid "settings.default_balloon_path" +msgstr "<example balloon>" + +msgid "settings.autoload" +msgstr "Autoload" + +msgid "settings.path" +msgstr "Path" + +msgid "settings.new_template" +msgstr "New dialogue files will start with template text" + +msgid "settings.missing_keys" +msgstr "Treat missing translation keys as errors" + +msgid "settings.missing_keys_hint" +msgstr "If you are using static translation keys then having this enabled will help you find any lines that you haven't added a key to yet." + +msgid "settings.characters_translations" +msgstr "Export character names in translation files" + +msgid "settings.wrap_long_lines" +msgstr "Wrap long lines" + +msgid "settings.include_failed_responses" +msgstr "Include responses with failed conditions" + +msgid "settings.ignore_missing_state_values" +msgstr "Skip over missing state value errors (not recommended)" + +msgid "settings.custom_test_scene" +msgstr "Custom test scene (must extend BaseDialogueTestScene)" + +msgid "settings.default_csv_locale" +msgstr "Default CSV Locale" + +msgid "settings.states_shortcuts" +msgstr "State Shortcuts" + +msgid "settings.states_message" +msgstr "If an autoload is enabled here you can refer to its properties and methods without having to use its name." + +msgid "settings.states_hint" +msgstr "ie. Instead of \"SomeState.some_property\" you could just use \"some_property\"" + +msgid "settings.recompile_warning" +msgstr "Changing these settings will force a recompile of all dialogue. Only change them if you know what you are doing." + +msgid "settings.create_lines_for_responses_with_characters" +msgstr "Create child dialogue line for responses with character names in them" + +msgid "settings.open_in_external_editor" +msgstr "Open dialogue files in external editor" + +msgid "settings.external_editor_warning" +msgstr "Note: Syntax highlighting and detailed error checking are not supported in external editors." + +msgid "settings.include_characters_in_translations" +msgstr "Include character names in translation exports" + +msgid "settings.include_notes_in_translations" +msgstr "Include notes (## comments) in translation exports" + +msgid "settings.check_for_updates" +msgstr "Check for updates" + +msgid "n_of_n" +msgstr "{index} of {total}" + +msgid "search.find" +msgstr "Find:" + +msgid "search.find_all" +msgstr "Find all..." + +msgid "search.placeholder" +msgstr "Text to search for" + +msgid "search.replace_placeholder" +msgstr "Text to replace it with" + +msgid "search.replace_selected" +msgstr "Replace selected" + +msgid "search.previous" +msgstr "Previous" + +msgid "search.next" +msgstr "Next" + +msgid "search.match_case" +msgstr "Match case" + +msgid "search.toggle_replace" +msgstr "Replace" + +msgid "search.replace_with" +msgstr "Replace with:" + +msgid "search.replace" +msgstr "Replace" + +msgid "search.replace_all" +msgstr "Replace all" + +msgid "files_list.filter" +msgstr "Filter files" + +msgid "titles_list.filter" +msgstr "Filter titles" + +msgid "errors.key_not_found" +msgstr "Key \"{key}\" not found." + +msgid "errors.line_and_message" +msgstr "Error at {line}, {column}: {message}" + +msgid "errors_in_script" +msgstr "You have errors in your script. Fix them and then try again." + +msgid "errors_with_build" +msgstr "You need to fix dialogue errors before you can run your game." + +msgid "errors.import_errors" +msgstr "There are errors in this imported file." + +msgid "errors.already_imported" +msgstr "File already imported." + +msgid "errors.duplicate_import" +msgstr "Duplicate import name." + +msgid "errors.unknown_using" +msgstr "Unknown autoload in using statement." + +msgid "errors.empty_title" +msgstr "Titles cannot be empty." + +msgid "errors.duplicate_title" +msgstr "There is already a title with that name." + +msgid "errors.nested_title" +msgstr "Titles cannot be indented." + +msgid "errors.invalid_title_string" +msgstr "Titles can only contain alphanumeric characters and numbers." + +msgid "errors.invalid_title_number" +msgstr "Titles cannot begin with a number." + +msgid "errors.unknown_title" +msgstr "Unknown title." + +msgid "errors.jump_to_invalid_title" +msgstr "This jump is pointing to an invalid title." + +msgid "errors.title_has_no_content" +msgstr "That title has no content. Maybe change this to a \"=> END\"." + +msgid "errors.invalid_expression" +msgstr "Expression is invalid." + +msgid "errors.unexpected_condition" +msgstr "Unexpected condition." + +msgid "errors.duplicate_id" +msgstr "This ID is already on another line." + +msgid "errors.missing_id" +msgstr "This line is missing an ID." + +msgid "errors.invalid_indentation" +msgstr "Invalid indentation." + +msgid "errors.condition_has_no_content" +msgstr "A condition line needs an indented line below it." + +msgid "errors.incomplete_expression" +msgstr "Incomplete expression." + +msgid "errors.invalid_expression_for_value" +msgstr "Invalid expression for value." + +msgid "errors.file_not_found" +msgstr "File not found." + +msgid "errors.unexpected_end_of_expression" +msgstr "Unexpected end of expression." + +msgid "errors.unexpected_function" +msgstr "Unexpected function." + +msgid "errors.unexpected_bracket" +msgstr "Unexpected bracket." + +msgid "errors.unexpected_closing_bracket" +msgstr "Unexpected closing bracket." + +msgid "errors.missing_closing_bracket" +msgstr "Missing closing bracket." + +msgid "errors.unexpected_operator" +msgstr "Unexpected operator." + +msgid "errors.unexpected_comma" +msgstr "Unexpected comma." + +msgid "errors.unexpected_colon" +msgstr "Unexpected colon." + +msgid "errors.unexpected_dot" +msgstr "Unexpected dot." + +msgid "errors.unexpected_boolean" +msgstr "Unexpected boolean." + +msgid "errors.unexpected_string" +msgstr "Unexpected string." + +msgid "errors.unexpected_number" +msgstr "Unexpected number." + +msgid "errors.unexpected_variable" +msgstr "Unexpected variable." + +msgid "errors.invalid_index" +msgstr "Invalid index." + +msgid "errors.unexpected_assignment" +msgstr "Unexpected assignment." + +msgid "errors.unknown" +msgstr "Unknown syntax." + +msgid "update.available" +msgstr "v{version} available" + +msgid "update.is_available_for_download" +msgstr "Version %s is available for download!" + +msgid "update.downloading" +msgstr "Downloading..." + +msgid "update.download_update" +msgstr "Download update" + +msgid "update.needs_reload" +msgstr "The project needs to be reloaded to install the update." + +msgid "update.reload_ok_button" +msgstr "Reload project" + +msgid "update.reload_cancel_button" +msgstr "Do it later" + +msgid "update.reload_project" +msgstr "Reload project" + +msgid "update.release_notes" +msgstr "Read release notes" + +msgid "update.success" +msgstr "Dialogue Manager is now v{version}." + +msgid "update.failed" +msgstr "There was a problem downloading the update." + +msgid "runtime.no_resource" +msgstr "No dialogue resource provided." + +msgid "runtime.no_content" +msgstr "\"{file_path}\" has no content." + +msgid "runtime.errors" +msgstr "You have {count} errors in your dialogue text." + +msgid "runtime.error_detail" +msgstr "Line {line}: {message}" + +msgid "runtime.errors_see_details" +msgstr "You have {count} errors in your dialogue text. See Output for details." + +msgid "runtime.invalid_expression" +msgstr "\"{expression}\" is not a valid expression: {error}" + +msgid "runtime.array_index_out_of_bounds" +msgstr "Index {index} out of bounds of array \"{array}\"." + +msgid "runtime.left_hand_size_cannot_be_assigned_to" +msgstr "Left hand side of expression cannot be assigned to." + +msgid "runtime.key_not_found" +msgstr "Key \"{key}\" not found in dictionary \"{dictionary}\"" + +msgid "runtime.property_not_found" +msgstr "\"{property}\" is not a property on any game states ({states})." + +msgid "runtime.property_not_found_missing_export" +msgstr "\"{property}\" is not a property on any game states ({states}). You might need to add an [Export] decorator." + +msgid "runtime.method_not_found" +msgstr "\"{method}\" is not a method on any game states ({states})" + +msgid "runtime.signal_not_found" +msgstr "\"{signal_name}\" is not a signal on any game states ({states})" + +msgid "runtime.method_not_callable" +msgstr "\"{method}\" is not a callable method on \"{object}\"" + +msgid "runtime.unknown_operator" +msgstr "Unknown operator." + +msgid "runtime.unknown_autoload" +msgstr "\"{autoload}\" doesn't appear to be a valid autoload." + +msgid "runtime.something_went_wrong" +msgstr "Something went wrong." + +msgid "runtime.expected_n_got_n_args" +msgstr "\"{method}\" was called with {received} arguments but it only has {expected}." + +msgid "runtime.unsupported_array_type" +msgstr "Array[{type}] isn't supported in mutations. Use Array as a type instead." + +msgid "runtime.dialogue_balloon_missing_start_method" +msgstr "Your dialogue balloon is missing a \"start\" or \"Start\" method." \ No newline at end of file diff --git a/addons/dialogue_manager/l10n/es.po b/addons/dialogue_manager/l10n/es.po new file mode 100644 index 0000000..3cbaa32 --- /dev/null +++ b/addons/dialogue_manager/l10n/es.po @@ -0,0 +1,457 @@ +# +msgid "" +msgstr "" +"Project-Id-Version: Dialogue Manager\n" +"POT-Creation-Date: 2024-02-25 20:58\n" +"PO-Revision-Date: 2024-02-25 20:58\n" +"Last-Translator: you <you@example.com>\n" +"Language-Team: Spanish <yourteam@example.com>\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "start_a_new_file" +msgstr "Crear un nuevo archivo" + +msgid "open_a_file" +msgstr "Abrir un archivo" + +msgid "open.open" +msgstr "Abrir..." + +msgid "open.no_recent_files" +msgstr "No hay archivos recientes" + +msgid "open.clear_recent_files" +msgstr "Limpiar archivos recientes" + +msgid "save_all_files" +msgstr "Guardar todos los archivos" + +msgid "test_dialogue" +msgstr "Diálogo de prueba" + +msgid "search_for_text" +msgstr "Buscar texto" + +msgid "insert" +msgstr "Insertar" + +msgid "translations" +msgstr "Traducciones" + +msgid "settings" +msgstr "Ajustes" + +msgid "show_support" +msgstr "Contribuye con Dialogue Manager" + +msgid "docs" +msgstr "Docs" + +msgid "insert.wave_bbcode" +msgstr "BBCode ondulado" + +msgid "insert.shake_bbcode" +msgstr "BBCode agitado" + +msgid "insert.typing_pause" +msgstr "Pausa de escritura" + +msgid "insert.typing_speed_change" +msgstr "Cambiar la velocidad de escritura" + +msgid "insert.auto_advance" +msgstr "Avance automático" + +msgid "insert.templates" +msgstr "Plantillas" + +msgid "insert.title" +msgstr "Título" + +msgid "insert.dialogue" +msgstr "Diálogo" + +msgid "insert.response" +msgstr "Respuesta" + +msgid "insert.random_lines" +msgstr "Líneas aleatorias" + +msgid "insert.random_text" +msgstr "Texto aleatorio" + +msgid "insert.actions" +msgstr "Acciones" + +msgid "insert.jump" +msgstr "Ir al título" + +msgid "insert.end_dialogue" +msgstr "Finalizar diálogo" + +msgid "generate_line_ids" +msgstr "Generar IDs de línea" + +msgid "save_characters_to_csv" +msgstr "Guardar los nombres de los personajes en un archivo CSV..." + +msgid "save_to_csv" +msgstr "Guardar líneas en CSV..." + +msgid "import_from_csv" +msgstr "Importar cambios de línea desde CSV..." + +msgid "confirm_close" +msgstr "¿Guardar los cambios en '{path}'?" + +msgid "confirm_close.save" +msgstr "Guardar cambios" + +msgid "confirm_close.discard" +msgstr "Descartar" + +msgid "buffer.save" +msgstr "Guardar" + +msgid "buffer.save_as" +msgstr "Guardar como..." + +msgid "buffer.close" +msgstr "Cerrar" + +msgid "buffer.close_all" +msgstr "Cerrar todo" + +msgid "buffer.close_other_files" +msgstr "Cerrar otros archivos" + +msgid "buffer.copy_file_path" +msgstr "Copiar la ruta del archivo" + +msgid "buffer.show_in_filesystem" +msgstr "Mostrar en el sistema de archivos" + +msgid "settings.invalid_test_scene" +msgstr "\"{path}\" no extiende BaseDialogueTestScene." + +msgid "settings.revert_to_default_test_scene" +msgstr "Revertir a la escena de prueba por defecto" + +msgid "settings.default_balloon_hint" +msgstr "" +"Globo personalizado para usar al llamar a \"DialogueManager.show_balloon()\"" + +msgid "settings.revert_to_default_balloon" +msgstr "Volver al globo predeterminado" + +msgid "settings.default_balloon_path" +msgstr "<globo de ejemplo>" + +msgid "settings.autoload" +msgstr "Autocarga" + +msgid "settings.path" +msgstr "Ruta" + +msgid "settings.new_template" +msgstr "Los nuevos archivos de diálogo empezarán con una plantilla" + +msgid "settings.missing_keys" +msgstr "Tratar las claves de traducción faltantes como errores" + +msgid "settings.missing_keys_hint" +msgstr "Si estás utilizando claves de traducción estáticas, tener esta opción habilitada te ayudará a encontrar cualquier línea a la que aún no le hayas añadido una clave." + +msgid "settings.characters_translations" +msgstr "Exportar nombres de personajes en archivos de traducción" + +msgid "settings.wrap_long_lines" +msgstr "Romper líneas largas" + +msgid "settings.include_failed_responses" +msgstr "Incluir respuestas con condiciones fallidas" + +msgid "settings.ignore_missing_state_values" +msgstr "Omitir errores de valores de estado faltantes (no recomendado)" + +msgid "settings.custom_test_scene" +msgstr "Escena de prueba personalizada (debe extender BaseDialogueTestScene)" + +msgid "settings.default_csv_locale" +msgstr "Localización CSV por defecto" + +msgid "settings.states_shortcuts" +msgstr "Atajos de teclado" + +msgid "settings.states_message" +msgstr "Si un autoload está habilitado aquí, puedes referirte a sus propiedades y métodos sin tener que usar su nombre." + +msgid "settings.states_hint" +msgstr "ie. En lugar de \"SomeState.some_property\" podría simplemente usar \"some_property\"" + +msgid "settings.recompile_warning" +msgstr "Cambiar estos ajustes obligará a recompilar todo el diálogo. Hazlo solo si sabes lo que estás haciendo." + +msgid "settings.create_lines_for_responses_with_characters" +msgstr "Crear línea de diálogo para respuestas con nombres de personajes dentro." + +msgid "settings.open_in_external_editor" +msgstr "Abrir archivos de diálogo en el editor externo" + +msgid "settings.external_editor_warning" +msgstr "Nota: El resaltado de sintaxis y la verificación detallada de errores no están soportados en editores externos." + +msgid "settings.include_characters_in_translations" +msgstr "Incluir nombres de personajes en las exportaciones de traducción" + +msgid "settings.include_notes_in_translations" +msgstr "Incluir notas (## comentarios) en las exportaciones de traducción" + +msgid "n_of_n" +msgstr "{index} de {total}" + +msgid "search.previous" +msgstr "Anterior" + +msgid "search.next" +msgstr "Siguiente" + +msgid "search.match_case" +msgstr "Coincidir mayúsculas/minúsculas" + +msgid "search.toggle_replace" +msgstr "Reemplazar" + +msgid "search.replace_with" +msgstr "Reemplazar con:" + +msgid "search.replace" +msgstr "Reemplazar" + +msgid "search.replace_all" +msgstr "Reemplazar todo" + +msgid "files_list.filter" +msgstr "Filtrar archivos" + +msgid "titles_list.filter" +msgstr "Filtrar títulos" + +msgid "errors.key_not_found" +msgstr "La tecla \"{key}\" no se encuentra." + +msgid "errors.line_and_message" +msgstr "Error en {line}, {column}: {message}" + +msgid "errors_in_script" +msgstr "Tienes errores en tu guion. Corrígelos y luego inténtalo de nuevo." + +msgid "errors_with_build" +msgstr "Debes corregir los errores de diálogo antes de poder ejecutar tu juego." + +msgid "errors.import_errors" +msgstr "Hay errores en este archivo importado." + +msgid "errors.already_imported" +msgstr "Archivo ya importado." + +msgid "errors.duplicate_import" +msgstr "Nombre de importación duplicado." + +msgid "errors.unknown_using" +msgstr "Autoload desconocida en la declaración de uso." + +msgid "errors.empty_title" +msgstr "Los títulos no pueden estar vacíos." + +msgid "errors.duplicate_title" +msgstr "Ya hay un título con ese nombre." + +msgid "errors.nested_title" +msgstr "Los títulos no pueden tener sangría." + +msgid "errors.invalid_title_string" +msgstr "Los títulos solo pueden contener caracteres alfanuméricos y números." + +msgid "errors.invalid_title_number" +msgstr "Los títulos no pueden empezar con un número." + +msgid "errors.unknown_title" +msgstr "Título desconocido." + +msgid "errors.jump_to_invalid_title" +msgstr "Este salto está apuntando a un título inválido." + +msgid "errors.title_has_no_content" +msgstr "Ese título no tiene contenido. Quizá cambiarlo a \"=> FIN\"." + +msgid "errors.invalid_expression" +msgstr "La expresión es inválida." + +msgid "errors.unexpected_condition" +msgstr "Condición inesperada." + +msgid "errors.duplicate_id" +msgstr "Este ID ya está en otra línea." + +msgid "errors.missing_id" +msgstr "Esta línea está sin ID." + +msgid "errors.invalid_indentation" +msgstr "Sangría no válida." + +msgid "errors.condition_has_no_content" +msgstr "Una línea de condición necesita una línea sangrada debajo de ella." + +msgid "errors.incomplete_expression" +msgstr "Expresión incompleta." + +msgid "errors.invalid_expression_for_value" +msgstr "Expresión no válida para valor." + +msgid "errors.file_not_found" +msgstr "Archivo no encontrado." + +msgid "errors.unexpected_end_of_expression" +msgstr "Fin de expresión inesperado." + +msgid "errors.unexpected_function" +msgstr "Función inesperada." + +msgid "errors.unexpected_bracket" +msgstr "Corchete inesperado." + +msgid "errors.unexpected_closing_bracket" +msgstr "Bracket de cierre inesperado." + +msgid "errors.missing_closing_bracket" +msgstr "Falta cerrar corchete." + +msgid "errors.unexpected_operator" +msgstr "Operador inesperado." + +msgid "errors.unexpected_comma" +msgstr "Coma inesperada." + +msgid "errors.unexpected_colon" +msgstr "Dos puntos inesperados" + +msgid "errors.unexpected_dot" +msgstr "Punto inesperado." + +msgid "errors.unexpected_boolean" +msgstr "Booleano inesperado." + +msgid "errors.unexpected_string" +msgstr "String inesperado." + +msgid "errors.unexpected_number" +msgstr "Número inesperado." + +msgid "errors.unexpected_variable" +msgstr "Variable inesperada." + +msgid "errors.invalid_index" +msgstr "Índice no válido." + +msgid "errors.unexpected_assignment" +msgstr "Asignación inesperada." + +msgid "errors.unknown" +msgstr "Sintaxis desconocida." + +msgid "update.available" +msgstr "v{version} disponible" + +msgid "update.is_available_for_download" +msgstr "¡La versión %s ya está disponible para su descarga!" + +msgid "update.downloading" +msgstr "Descargando..." + +msgid "update.download_update" +msgstr "Descargar actualización" + +msgid "update.needs_reload" +msgstr "El proyecto debe ser recargado para instalar la actualización." + +msgid "update.reload_ok_button" +msgstr "Recargar proyecto" + +msgid "update.reload_cancel_button" +msgstr "Hazlo más tarde" + +msgid "update.reload_project" +msgstr "Recargar proyecto" + +msgid "update.release_notes" +msgstr "Leer las notas de la versión" + +msgid "update.success" +msgstr "El Gestor de Diálogo ahora es v{versión}." + +msgid "update.failed" +msgstr "Hubo un problema al descargar la actualización." + +msgid "runtime.no_resource" +msgstr "Recurso de diálogo no proporcionado." + +msgid "runtime.no_content" +msgstr "\"{file_path}\" no tiene contenido." + +msgid "runtime.errors" +msgstr "Tienes {count} errores en tu diálogo de texto." + +msgid "runtime.error_detail" +msgstr "Línea {line}: {message}" + +msgid "runtime.errors_see_details" +msgstr "Tienes {count} errores en tu texto de diálogo. Consulta la salida para más detalles." + +msgid "runtime.invalid_expression" +msgstr "\"{expression}\" no es una expresión válida: {error}" + +msgid "runtime.array_index_out_of_bounds" +msgstr "Índice {index} fuera de los límites del array \"{array}\"." + +msgid "runtime.left_hand_size_cannot_be_assigned_to" +msgstr "El lado izquierdo de la expresión no se puede asignar." + +msgid "runtime.key_not_found" +msgstr "Clave \"{key}\" no encontrada en el diccionario \"{dictionary}\"" + +msgid "runtime.property_not_found" +msgstr "\"{property}\" no es una propiedad en ningún estado del juego ({states})." + +msgid "runtime.property_not_found_missing_export" +msgstr "\"{property}\" no es una propiedad en ningún estado del juego ({states}). Es posible que necesites añadir un decorador [Export]." + +msgid "runtime.method_not_found" +msgstr "\"{method}\" no es un método en ningún estado del juego ({states})" + +msgid "runtime.signal_not_found" +msgstr "\"{signal_name}\" no es una señal en ningún estado del juego ({states})" + +msgid "runtime.method_not_callable" +msgstr "\"{method}\" no es un método llamable en \"{object}\"" + +msgid "runtime.unknown_operator" +msgstr "Operador desconocido." + +msgid "runtime.unknown_autoload" +msgstr "\"{autoload}\" parece no ser un autoload válido." + +msgid "runtime.something_went_wrong" +msgstr "Algo salió mal." + +msgid "runtime.expected_n_got_n_args" +msgstr "El método \"{method}\" se llamó con {received} argumentos, pero solo tiene {expected}." + +msgid "runtime.unsupported_array_type" +msgstr "Array[{type}] no está soportado en mutaciones. Utiliza Array como tipo en su lugar." + +msgid "runtime.dialogue_balloon_missing_start_method" +msgstr "Tu globo de diálogo no tiene un método \"start\" o \"Start\"." diff --git a/addons/dialogue_manager/l10n/translations.pot b/addons/dialogue_manager/l10n/translations.pot new file mode 100644 index 0000000..4aeec3b --- /dev/null +++ b/addons/dialogue_manager/l10n/translations.pot @@ -0,0 +1,471 @@ +msgid "" +msgstr "" +"Project-Id-Version: Dialogue Manager\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8-bit\n" + +msgid "start_a_new_file" +msgstr "" + +msgid "open_a_file" +msgstr "" + +msgid "open.open" +msgstr "" + +msgid "open.no_recent_files" +msgstr "" + +msgid "open.clear_recent_files" +msgstr "" + +msgid "save_all_files" +msgstr "" + +msgid "find_in_files" +msgstr "" + +msgid "test_dialogue" +msgstr "" + +msgid "search_for_text" +msgstr "" + +msgid "insert" +msgstr "" + +msgid "translations" +msgstr "" + +msgid "settings" +msgstr "" + +msgid "sponsor" +msgstr "" + +msgid "show_support" +msgstr "" + +msgid "docs" +msgstr "" + +msgid "insert.wave_bbcode" +msgstr "" + +msgid "insert.shake_bbcode" +msgstr "" + +msgid "insert.typing_pause" +msgstr "" + +msgid "insert.typing_speed_change" +msgstr "" + +msgid "insert.auto_advance" +msgstr "" + +msgid "insert.templates" +msgstr "" + +msgid "insert.title" +msgstr "" + +msgid "insert.dialogue" +msgstr "" + +msgid "insert.response" +msgstr "" + +msgid "insert.random_lines" +msgstr "" + +msgid "insert.random_text" +msgstr "" + +msgid "insert.actions" +msgstr "" + +msgid "insert.jump" +msgstr "" + +msgid "insert.end_dialogue" +msgstr "" + +msgid "generate_line_ids" +msgstr "" + +msgid "save_to_csv" +msgstr "" + +msgid "import_from_csv" +msgstr "" + +msgid "confirm_close" +msgstr "" + +msgid "confirm_close.save" +msgstr "" + +msgid "confirm_close.discard" +msgstr "" + +msgid "buffer.save" +msgstr "" + +msgid "buffer.save_as" +msgstr "" + +msgid "buffer.close" +msgstr "" + +msgid "buffer.close_all" +msgstr "" + +msgid "buffer.close_other_files" +msgstr "" + +msgid "buffer.copy_file_path" +msgstr "" + +msgid "buffer.show_in_filesystem" +msgstr "" + +msgid "settings.invalid_test_scene" +msgstr "" + +msgid "settings.revert_to_default_test_scene" +msgstr "" + +msgid "settings.default_balloon_hint" +msgstr "" + +msgid "settings.revert_to_default_balloon" +msgstr "" + +msgid "settings.default_balloon_path" +msgstr "" + +msgid "settings.autoload" +msgstr "" + +msgid "settings.path" +msgstr "" + +msgid "settings.new_template" +msgstr "" + +msgid "settings.missing_keys" +msgstr "" + +msgid "settings.missing_keys_hint" +msgstr "" + +msgid "settings.characters_translations" +msgstr "" + +msgid "settings.wrap_long_lines" +msgstr "" + +msgid "settings.include_failed_responses" +msgstr "" + +msgid "settings.ignore_missing_state_values" +msgstr "" + +msgid "settings.custom_test_scene" +msgstr "" + +msgid "settings.default_csv_locale" +msgstr "" + +msgid "settings.states_shortcuts" +msgstr "" + +msgid "settings.states_message" +msgstr "" + +msgid "settings.states_hint" +msgstr "" + +msgid "settings.recompile_warning" +msgstr "" + +msgid "settings.create_lines_for_responses_with_characters" +msgstr "" + +msgid "settings.open_in_external_editor" +msgstr "" + +msgid "settings.external_editor_warning" +msgstr "" + +msgid "settings.include_characters_in_translations" +msgstr "" + +msgid "settings.include_notes_in_translations" +msgstr "" + +msgid "settings.check_for_updates" +msgstr "" + +msgid "n_of_n" +msgstr "" + +msgid "search.find" +msgstr "" + +msgid "search.find_all" +msgstr "" + +msgid "search.placeholder" +msgstr "" + +msgid "search.replace_placeholder" +msgstr "" + +msgid "search.replace_selected" +msgstr "" + +msgid "search.previous" +msgstr "" + +msgid "search.next" +msgstr "" + +msgid "search.match_case" +msgstr "" + +msgid "search.toggle_replace" +msgstr "" + +msgid "search.replace_with" +msgstr "" + +msgid "search.replace" +msgstr "" + +msgid "search.replace_all" +msgstr "" + +msgid "files_list.filter" +msgstr "" + +msgid "titles_list.filter" +msgstr "" + +msgid "errors.key_not_found" +msgstr "" + +msgid "errors.line_and_message" +msgstr "" + +msgid "errors_in_script" +msgstr "" + +msgid "errors_with_build" +msgstr "" + +msgid "errors.import_errors" +msgstr "" + +msgid "errors.already_imported" +msgstr "" + +msgid "errors.duplicate_import" +msgstr "" + +msgid "errors.unknown_using" +msgstr "" + +msgid "errors.empty_title" +msgstr "" + +msgid "errors.duplicate_title" +msgstr "" + +msgid "errors.nested_title" +msgstr "" + +msgid "errors.invalid_title_string" +msgstr "" + +msgid "errors.invalid_title_number" +msgstr "" + +msgid "errors.unknown_title" +msgstr "" + +msgid "errors.jump_to_invalid_title" +msgstr "" + +msgid "errors.title_has_no_content" +msgstr "" + +msgid "errors.invalid_expression" +msgstr "" + +msgid "errors.unexpected_condition" +msgstr "" + +msgid "errors.duplicate_id" +msgstr "" + +msgid "errors.missing_id" +msgstr "" + +msgid "errors.invalid_indentation" +msgstr "" + +msgid "errors.condition_has_no_content" +msgstr "" + +msgid "errors.incomplete_expression" +msgstr "" + +msgid "errors.invalid_expression_for_value" +msgstr "" + +msgid "errors.file_not_found" +msgstr "" + +msgid "errors.unexpected_end_of_expression" +msgstr "" + +msgid "errors.unexpected_function" +msgstr "" + +msgid "errors.unexpected_bracket" +msgstr "" + +msgid "errors.unexpected_closing_bracket" +msgstr "" + +msgid "errors.missing_closing_bracket" +msgstr "" + +msgid "errors.unexpected_operator" +msgstr "" + +msgid "errors.unexpected_comma" +msgstr "" + +msgid "errors.unexpected_colon" +msgstr "" + +msgid "errors.unexpected_dot" +msgstr "" + +msgid "errors.unexpected_boolean" +msgstr "" + +msgid "errors.unexpected_string" +msgstr "" + +msgid "errors.unexpected_number" +msgstr "" + +msgid "errors.unexpected_variable" +msgstr "" + +msgid "errors.invalid_index" +msgstr "" + +msgid "errors.unexpected_assignment" +msgstr "" + +msgid "errors.unknown" +msgstr "" + +msgid "update.available" +msgstr "" + +msgid "update.is_available_for_download" +msgstr "" + +msgid "update.downloading" +msgstr "" + +msgid "update.download_update" +msgstr "" + +msgid "update.needs_reload" +msgstr "" + +msgid "update.reload_ok_button" +msgstr "" + +msgid "update.reload_cancel_button" +msgstr "" + +msgid "update.reload_project" +msgstr "" + +msgid "update.release_notes" +msgstr "" + +msgid "update.success" +msgstr "" + +msgid "update.failed" +msgstr "" + +msgid "runtime.no_resource" +msgstr "" + +msgid "runtime.no_content" +msgstr "" + +msgid "runtime.errors" +msgstr "" + +msgid "runtime.error_detail" +msgstr "" + +msgid "runtime.errors_see_details" +msgstr "" + +msgid "runtime.invalid_expression" +msgstr "" + +msgid "runtime.array_index_out_of_bounds" +msgstr "" + +msgid "runtime.left_hand_size_cannot_be_assigned_to" +msgstr "" + +msgid "runtime.key_not_found" +msgstr "" + +msgid "runtime.property_not_found" +msgstr "" + +msgid "runtime.property_not_found_missing_export" +msgstr "" + +msgid "runtime.method_not_found" +msgstr "" + +msgid "runtime.signal_not_found" +msgstr "" + +msgid "runtime.method_not_callable" +msgstr "" + +msgid "runtime.unknown_operator" +msgstr "" + +msgid "runtime.unknown_autoload" +msgstr "" + +msgid "runtime.something_went_wrong" +msgstr "" + +msgid "runtime.expected_n_got_n_args" +msgstr "" + +msgid "runtime.unsupported_array_type" +msgstr "" + +msgid "runtime.dialogue_balloon_missing_start_method" +msgstr "" \ No newline at end of file diff --git a/addons/dialogue_manager/l10n/zh.po b/addons/dialogue_manager/l10n/zh.po new file mode 100644 index 0000000..b7f032f --- /dev/null +++ b/addons/dialogue_manager/l10n/zh.po @@ -0,0 +1,408 @@ +msgid "" +msgstr "" +"Project-Id-Version: Dialogue Manager\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: penghao123456、憨憨羊の宇航鸽鸽\n" +"Language: zh\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.4\n" + +msgid "start_a_new_file" +msgstr "创建新文件" + +msgid "open_a_file" +msgstr "打开已有文件" + +msgid "open.open" +msgstr "打开……" + +msgid "open.no_recent_files" +msgstr "无历史记录" + +msgid "open.clear_recent_files" +msgstr "清空历史记录" + +msgid "save_all_files" +msgstr "保存所有文件" + +msgid "test_dialogue" +msgstr "测试对话" + +msgid "search_for_text" +msgstr "查找……" + +msgid "insert" +msgstr "插入" + +msgid "translations" +msgstr "翻译" + +msgid "settings" +msgstr "设置" + +msgid "show_support" +msgstr "支持 Dialogue Manager" + +msgid "docs" +msgstr "文档" + +msgid "insert.wave_bbcode" +msgstr "BBCode [lb]wave[rb]" + +msgid "insert.shake_bbcode" +msgstr "BBCode [lb]wave[rb]" + +msgid "insert.typing_pause" +msgstr "输入间隔" + +msgid "insert.typing_speed_change" +msgstr "输入速度变更" + +msgid "insert.auto_advance" +msgstr "自动切行" + +msgid "insert.templates" +msgstr "模板" + +msgid "insert.title" +msgstr "标题" + +msgid "insert.dialogue" +msgstr "对话" + +msgid "insert.response" +msgstr "回复选项" + +msgid "insert.random_lines" +msgstr "随机行" + +msgid "insert.random_text" +msgstr "随机文本" + +msgid "insert.actions" +msgstr "操作" + +msgid "insert.jump" +msgstr "标题间跳转" + +msgid "insert.end_dialogue" +msgstr "结束对话" + +msgid "generate_line_ids" +msgstr "生成行 ID" + +msgid "save_to_csv" +msgstr "生成 CSV" + +msgid "import_from_csv" +msgstr "从 CSV 导入" + +msgid "confirm_close" +msgstr "是否要保存到“{path}”?" + +msgid "confirm_close.save" +msgstr "保存" + +msgid "confirm_close.discard" +msgstr "不保存" + +msgid "buffer.save" +msgstr "保存" + +msgid "buffer.save_as" +msgstr "另存为……" + +msgid "buffer.close" +msgstr "关闭" + +msgid "buffer.close_all" +msgstr "全部关闭" + +msgid "buffer.close_other_files" +msgstr "关闭其他文件" + +msgid "buffer.copy_file_path" +msgstr "复制文件路径" + +msgid "buffer.show_in_filesystem" +msgstr "在 Godot 侧边栏中显示" + +msgid "settings.revert_to_default_test_scene" +msgstr "重置测试场景设定" + +msgid "settings.autoload" +msgstr "Autoload" + +msgid "settings.path" +msgstr "路径" + +msgid "settings.new_template" +msgstr "新建文件时自动插入模板" + +msgid "settings.missing_keys" +msgstr "将翻译键缺失视为错误" + +msgid "settings.missing_keys_hint" +msgstr "如果你使用静态键,这将会帮助你寻找未添加至翻译文件的键。" + +msgid "settings.characters_translations" +msgstr "在翻译文件中导出角色名。" + +msgid "settings.wrap_long_lines" +msgstr "自动折行" + +msgid "settings.include_failed_responses" +msgstr "在判断条件失败时仍显示回复选项" + +msgid "settings.ignore_missing_state_values" +msgstr "忽略全局变量缺失错误(不建议)" + +msgid "settings.custom_test_scene" +msgstr "自定义测试场景(必须继承自BaseDialogueTestScene)" + +msgid "settings.default_csv_locale" +msgstr "默认 CSV 区域格式" + +msgid "settings.states_shortcuts" +msgstr "全局变量映射" + +msgid "settings.states_message" +msgstr "当一个 Autoload 在这里被勾选,他的所有成员会被映射为全局变量。" + +msgid "settings.states_hint" +msgstr "比如,当你开启对于“Foo”的映射时,你可以将“Foo.bar”简写成“bar”。" + +msgid "n_of_n" +msgstr "第{index}个,共{total}个" + +msgid "search.previous" +msgstr "查找上一个" + +msgid "search.next" +msgstr "查找下一个" + +msgid "search.match_case" +msgstr "大小写敏感" + +msgid "search.toggle_replace" +msgstr "替换" + +msgid "search.replace_with" +msgstr "替换为" + +msgid "search.replace" +msgstr "替换" + +msgid "search.replace_all" +msgstr "全部替换" + +msgid "files_list.filter" +msgstr "查找文件" + +msgid "titles_list.filter" +msgstr "查找标题" + +msgid "errors.key_not_found" +msgstr "键“{key}”未找到" + +msgid "errors.line_and_message" +msgstr "第{line}行第{colume}列发生错误:{message}" + +msgid "errors_in_script" +msgstr "你的脚本中存在错误。请修复错误,然后重试。" + +msgid "errors_with_build" +msgstr "请先解决 Dialogue 中的错误。" + +msgid "errors.import_errors" +msgstr "被导入的文件存在问题。" + +msgid "errors.already_imported" +msgstr "文件已被导入。" + +msgid "errors.duplicate_import" +msgstr "导入名不能重复。" + +msgid "errors.empty_title" +msgstr "标题名不能为空。" + +msgid "errors.duplicate_title" +msgstr "标题名不能重复。" + +msgid "errors.nested_title" +msgstr "标题不能嵌套。" + +msgid "errors.invalid_title_string" +msgstr "标题名无效。" + +msgid "errors.invalid_title_number" +msgstr "标题不能以数字开始。" + +msgid "errors.unknown_title" +msgstr "标题未定义。" + +msgid "errors.jump_to_invalid_title" +msgstr "标题名无效。" + +msgid "errors.title_has_no_content" +msgstr "目标标题为空。请替换为“=> END”。" + +msgid "errors.invalid_expression" +msgstr "表达式无效。" + +msgid "errors.unexpected_condition" +msgstr "未知条件。" + +msgid "errors.duplicate_id" +msgstr "ID 重复。" + +msgid "errors.missing_id" +msgstr "ID 不存在。" + +msgid "errors.invalid_indentation" +msgstr "缩进无效。" + +msgid "errors.condition_has_no_content" +msgstr "条件下方不能为空。" + +msgid "errors.incomplete_expression" +msgstr "不完整的表达式。" + +msgid "errors.invalid_expression_for_value" +msgstr "无效的赋值表达式。" + +msgid "errors.file_not_found" +msgstr "文件不存在。" + +msgid "errors.unexpected_end_of_expression" +msgstr "表达式 end 不应存在。" + +msgid "errors.unexpected_function" +msgstr "函数不应存在。" + +msgid "errors.unexpected_bracket" +msgstr "方括号不应存在。" + +msgid "errors.unexpected_closing_bracket" +msgstr "方括号不应存在。" + +msgid "errors.missing_closing_bracket" +msgstr "闭方括号不存在。" + +msgid "errors.unexpected_operator" +msgstr "操作符不应存在。" + +msgid "errors.unexpected_comma" +msgstr "逗号不应存在。" + +msgid "errors.unexpected_colon" +msgstr "冒号不应存在。" + +msgid "errors.unexpected_dot" +msgstr "句号不应存在。" + +msgid "errors.unexpected_boolean" +msgstr "布尔值不应存在。" + +msgid "errors.unexpected_string" +msgstr "字符串不应存在。" + +msgid "errors.unexpected_number" +msgstr "数字不应存在。" + +msgid "errors.unexpected_variable" +msgstr "标识符不应存在。" + +msgid "errors.invalid_index" +msgstr "索引无效。" + +msgid "errors.unexpected_assignment" +msgstr "不应在条件判断中使用 = ,应使用 == 。" + +msgid "errors.unknown" +msgstr "语法错误。" + +msgid "update.available" +msgstr "v{version} 更新可用。" + +msgid "update.is_available_for_download" +msgstr "v%s 已经可以下载。" + +msgid "update.downloading" +msgstr "正在下载更新……" + +msgid "update.download_update" +msgstr "下载" + +msgid "update.needs_reload" +msgstr "需要重新加载项目以应用更新。" + +msgid "update.reload_ok_button" +msgstr "重新加载" + +msgid "update.reload_cancel_button" +msgstr "暂不重新加载" + +msgid "update.reload_project" +msgstr "重新加载" + +msgid "update.release_notes" +msgstr "查看发行注记" + +msgid "update.success" +msgstr "v{version} 已成功安装并应用。" + +msgid "update.failed" +msgstr "更新失败。" + +msgid "runtime.no_resource" +msgstr "找不到资源。" + +msgid "runtime.no_content" +msgstr "资源“{file_path}”为空。" + +msgid "runtime.errors" +msgstr "文件中存在{errrors}个错误。" + +msgid "runtime.error_detail" +msgstr "第{index}行:{message}" + +msgid "runtime.errors_see_details" +msgstr "文件中存在{errrors}个错误。请查看调试输出。" + +msgid "runtime.invalid_expression" +msgstr "表达式“{expression}”无效:{error}" + +msgid "runtime.array_index_out_of_bounds" +msgstr "数组索引“{index}”越界。(数组名:“{array}”)" + +msgid "runtime.left_hand_size_cannot_be_assigned_to" +msgstr "表达式左侧的变量无法被赋值。" + +msgid "runtime.key_not_found" +msgstr "键“{key}”在字典“{dictionary}”中不存在。" + +msgid "runtime.property_not_found" +msgstr "“{property}”不存在。(全局变量:{states})" + +msgid "runtime.property_not_found_missing_export" +msgstr "“{property}”不存在。(全局变量:{states})你可能需要添加一个修饰词 [Export]。" + +msgid "runtime.method_not_found" +msgstr "“{method}”不存在。(全局变量:{states})" + +msgid "runtime.signal_not_found" +msgstr "“{sighal_name}”不存在。(全局变量:{states})" + +msgid "runtime.method_not_callable" +msgstr "{method}不是对象“{object}”上的函数。" + +msgid "runtime.unknown_operator" +msgstr "未知操作符。" + +msgid "runtime.something_went_wrong" +msgstr "有什么出错了。" diff --git a/addons/dialogue_manager/l10n/zh_TW.po b/addons/dialogue_manager/l10n/zh_TW.po new file mode 100644 index 0000000..3bcf153 --- /dev/null +++ b/addons/dialogue_manager/l10n/zh_TW.po @@ -0,0 +1,408 @@ +msgid "" +msgstr "" +"Project-Id-Version: Dialogue Manager\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: 憨憨羊の宇航鴿鴿\n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.4\n" + +msgid "start_a_new_file" +msgstr "創建新檔案" + +msgid "open_a_file" +msgstr "開啟已有檔案" + +msgid "open.open" +msgstr "開啟……" + +msgid "open.no_recent_files" +msgstr "無歷史記錄" + +msgid "open.clear_recent_files" +msgstr "清空歷史記錄" + +msgid "save_all_files" +msgstr "儲存所有檔案" + +msgid "test_dialogue" +msgstr "測試對話" + +msgid "search_for_text" +msgstr "搜尋……" + +msgid "insert" +msgstr "插入" + +msgid "translations" +msgstr "翻譯" + +msgid "settings" +msgstr "設定" + +msgid "show_support" +msgstr "支援 Dialogue Manager" + +msgid "docs" +msgstr "文檔" + +msgid "insert.wave_bbcode" +msgstr "BBCode [lb]wave[rb]" + +msgid "insert.shake_bbcode" +msgstr "BBCode [lb]wave[rb]" + +msgid "insert.typing_pause" +msgstr "輸入間隔" + +msgid "insert.typing_speed_change" +msgstr "輸入速度變更" + +msgid "insert.auto_advance" +msgstr "自動切行" + +msgid "insert.templates" +msgstr "模板" + +msgid "insert.title" +msgstr "標題" + +msgid "insert.dialogue" +msgstr "對話" + +msgid "insert.response" +msgstr "回覆選項" + +msgid "insert.random_lines" +msgstr "隨機行" + +msgid "insert.random_text" +msgstr "隨機文本" + +msgid "insert.actions" +msgstr "操作" + +msgid "insert.jump" +msgstr "標題間跳轉" + +msgid "insert.end_dialogue" +msgstr "結束對話" + +msgid "generate_line_ids" +msgstr "生成行 ID" + +msgid "save_to_csv" +msgstr "生成 CSV" + +msgid "import_from_csv" +msgstr "從 CSV 匯入" + +msgid "confirm_close" +msgstr "是否要儲存到“{path}”?" + +msgid "confirm_close.save" +msgstr "儲存" + +msgid "confirm_close.discard" +msgstr "不儲存" + +msgid "buffer.save" +msgstr "儲存" + +msgid "buffer.save_as" +msgstr "儲存爲……" + +msgid "buffer.close" +msgstr "關閉" + +msgid "buffer.close_all" +msgstr "全部關閉" + +msgid "buffer.close_other_files" +msgstr "關閉其他檔案" + +msgid "buffer.copy_file_path" +msgstr "複製檔案位置" + +msgid "buffer.show_in_filesystem" +msgstr "在 Godot 側邊欄中顯示" + +msgid "settings.revert_to_default_test_scene" +msgstr "重置測試場景設定" + +msgid "settings.autoload" +msgstr "Autoload" + +msgid "settings.path" +msgstr "路徑" + +msgid "settings.new_template" +msgstr "新建檔案時自動插入模板" + +msgid "settings.missing_keys" +msgstr "將翻譯鍵缺失視爲錯誤" + +msgid "settings.missing_keys_hint" +msgstr "如果你使用靜態鍵,這將會幫助你尋找未添加至翻譯檔案的鍵。" + +msgid "settings.wrap_long_lines" +msgstr "自動折行" + +msgid "settings.characters_translations" +msgstr "在翻譯檔案中匯出角色名。" + +msgid "settings.include_failed_responses" +msgstr "在判斷條件失敗時仍顯示回復選項" + +msgid "settings.ignore_missing_state_values" +msgstr "忽略全局變量缺失錯誤(不建議)" + +msgid "settings.custom_test_scene" +msgstr "自訂測試場景(必須繼承自BaseDialogueTestScene)" + +msgid "settings.default_csv_locale" +msgstr "預設 CSV 區域格式" + +msgid "settings.states_shortcuts" +msgstr "全局變量映射" + +msgid "settings.states_message" +msgstr "當一個 Autoload 在這裏被勾選,他的所有成員會被映射爲全局變量。" + +msgid "settings.states_hint" +msgstr "比如,當你開啓對於“Foo”的映射時,你可以將“Foo.bar”簡寫成“bar”。" + +msgid "n_of_n" +msgstr "第{index}個,共{total}個" + +msgid "search.previous" +msgstr "搜尋上一個" + +msgid "search.next" +msgstr "搜尋下一個" + +msgid "search.match_case" +msgstr "大小寫敏感" + +msgid "search.toggle_replace" +msgstr "替換" + +msgid "search.replace_with" +msgstr "替換爲" + +msgid "search.replace" +msgstr "替換" + +msgid "search.replace_all" +msgstr "全部替換" + +msgid "files_list.filter" +msgstr "搜尋檔案" + +msgid "titles_list.filter" +msgstr "搜尋標題" + +msgid "errors.key_not_found" +msgstr "鍵“{key}”未找到" + +msgid "errors.line_and_message" +msgstr "第{line}行第{colume}列發生錯誤:{message}" + +msgid "errors_in_script" +msgstr "你的腳本中存在錯誤。請修復錯誤,然後重試。" + +msgid "errors_with_build" +msgstr "請先解決 Dialogue 中的錯誤。" + +msgid "errors.import_errors" +msgstr "被匯入的檔案存在問題。" + +msgid "errors.already_imported" +msgstr "檔案已被匯入。" + +msgid "errors.duplicate_import" +msgstr "匯入名不能重複。" + +msgid "errors.empty_title" +msgstr "標題名不能爲空。" + +msgid "errors.duplicate_title" +msgstr "標題名不能重複。" + +msgid "errors.nested_title" +msgstr "標題不能嵌套。" + +msgid "errors.invalid_title_string" +msgstr "標題名無效。" + +msgid "errors.invalid_title_number" +msgstr "標題不能以數字開始。" + +msgid "errors.unknown_title" +msgstr "標題未定義。" + +msgid "errors.jump_to_invalid_title" +msgstr "標題名無效。" + +msgid "errors.title_has_no_content" +msgstr "目標標題爲空。請替換爲“=> END”。" + +msgid "errors.invalid_expression" +msgstr "表達式無效。" + +msgid "errors.unexpected_condition" +msgstr "未知條件。" + +msgid "errors.duplicate_id" +msgstr "ID 重複。" + +msgid "errors.missing_id" +msgstr "ID 不存在。" + +msgid "errors.invalid_indentation" +msgstr "縮進無效。" + +msgid "errors.condition_has_no_content" +msgstr "條件下方不能爲空。" + +msgid "errors.incomplete_expression" +msgstr "不完整的表達式。" + +msgid "errors.invalid_expression_for_value" +msgstr "無效的賦值表達式。" + +msgid "errors.file_not_found" +msgstr "檔案不存在。" + +msgid "errors.unexpected_end_of_expression" +msgstr "表達式 end 不應存在。" + +msgid "errors.unexpected_function" +msgstr "函數不應存在。" + +msgid "errors.unexpected_bracket" +msgstr "方括號不應存在。" + +msgid "errors.unexpected_closing_bracket" +msgstr "方括號不應存在。" + +msgid "errors.missing_closing_bracket" +msgstr "閉方括號不存在。" + +msgid "errors.unexpected_operator" +msgstr "操作符不應存在。" + +msgid "errors.unexpected_comma" +msgstr "逗號不應存在。" + +msgid "errors.unexpected_colon" +msgstr "冒號不應存在。" + +msgid "errors.unexpected_dot" +msgstr "句號不應存在。" + +msgid "errors.unexpected_boolean" +msgstr "布爾值不應存在。" + +msgid "errors.unexpected_string" +msgstr "字符串不應存在。" + +msgid "errors.unexpected_number" +msgstr "數字不應存在。" + +msgid "errors.unexpected_variable" +msgstr "標識符不應存在。" + +msgid "errors.invalid_index" +msgstr "索引無效。" + +msgid "errors.unexpected_assignment" +msgstr "不應在條件判斷中使用 = ,應使用 == 。" + +msgid "errors.unknown" +msgstr "語法錯誤。" + +msgid "update.available" +msgstr "v{version} 更新可用。" + +msgid "update.is_available_for_download" +msgstr "v%s 已經可以下載。" + +msgid "update.downloading" +msgstr "正在下載更新……" + +msgid "update.download_update" +msgstr "下載" + +msgid "update.needs_reload" +msgstr "需要重新加載項目以套用更新。" + +msgid "update.reload_ok_button" +msgstr "重新加載" + +msgid "update.reload_cancel_button" +msgstr "暫不重新加載" + +msgid "update.reload_project" +msgstr "重新加載" + +msgid "update.release_notes" +msgstr "查看發行註記" + +msgid "update.success" +msgstr "v{version} 已成功安裝並套用。" + +msgid "update.failed" +msgstr "更新失敗。" + +msgid "runtime.no_resource" +msgstr "找不到資源。" + +msgid "runtime.no_content" +msgstr "資源“{file_path}”爲空。" + +msgid "runtime.errors" +msgstr "檔案中存在{errrors}個錯誤。" + +msgid "runtime.error_detail" +msgstr "第{index}行:{message}" + +msgid "runtime.errors_see_details" +msgstr "檔案中存在{errrors}個錯誤。請查看調試輸出。" + +msgid "runtime.invalid_expression" +msgstr "表達式“{expression}”無效:{error}" + +msgid "runtime.array_index_out_of_bounds" +msgstr "數組索引“{index}”越界。(數組名:“{array}”)" + +msgid "runtime.left_hand_size_cannot_be_assigned_to" +msgstr "表達式左側的變量無法被賦值。" + +msgid "runtime.key_not_found" +msgstr "鍵“{key}”在字典“{dictionary}”中不存在。" + +msgid "runtime.property_not_found" +msgstr "“{property}”不存在。(全局變量:{states})" + +msgid "runtime.method_not_found" +msgstr "“{method}”不存在。(全局變量:{states})" + +msgid "runtime.signal_not_found" +msgstr "“{sighal_name}”不存在。(全局變量:{states})" + +msgid "runtime.property_not_found_missing_export" +msgstr "“{property}”不存在。(全局變量:{states})你可能需要添加一個修飾詞 [Export]。" + +msgid "runtime.method_not_callable" +msgstr "{method}不是對象“{object}”上的函數。" + +msgid "runtime.unknown_operator" +msgstr "未知操作符。" + +msgid "runtime.something_went_wrong" +msgstr "有什麼出錯了。" diff --git a/addons/dialogue_manager/plugin.cfg b/addons/dialogue_manager/plugin.cfg new file mode 100644 index 0000000..572ad9f --- /dev/null +++ b/addons/dialogue_manager/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Dialogue Manager" +description="A simple but powerful branching dialogue system" +author="Nathan Hoad" +version="2.38.0" +script="plugin.gd" diff --git a/addons/dialogue_manager/plugin.gd b/addons/dialogue_manager/plugin.gd new file mode 100644 index 0000000..70836f3 --- /dev/null +++ b/addons/dialogue_manager/plugin.gd @@ -0,0 +1,276 @@ +@tool +extends EditorPlugin + + +const DialogueConstants = preload("./constants.gd") +const DialogueImportPlugin = preload("./import_plugin.gd") +const DialogueTranslationParserPlugin = preload("./editor_translation_parser_plugin.gd") +const DialogueSettings = preload("./settings.gd") +const DialogueCache = preload("./components/dialogue_cache.gd") +const MainView = preload("./views/main_view.tscn") + + +var import_plugin: DialogueImportPlugin +var translation_parser_plugin: DialogueTranslationParserPlugin +var main_view +var dialogue_cache: DialogueCache + + +func _enter_tree() -> void: + add_autoload_singleton("DialogueManager", get_plugin_path() + "/dialogue_manager.gd") + + if Engine.is_editor_hint(): + Engine.set_meta("DialogueManagerPlugin", self) + + DialogueSettings.prepare() + + import_plugin = DialogueImportPlugin.new() + add_import_plugin(import_plugin) + + translation_parser_plugin = DialogueTranslationParserPlugin.new() + add_translation_parser_plugin(translation_parser_plugin) + + main_view = MainView.instantiate() + main_view.editor_plugin = self + get_editor_interface().get_editor_main_screen().add_child(main_view) + _make_visible(false) + + dialogue_cache = DialogueCache.new() + main_view.add_child(dialogue_cache) + Engine.set_meta("DialogueCache", dialogue_cache) + + _update_localization() + + get_editor_interface().get_file_system_dock().files_moved.connect(_on_files_moved) + get_editor_interface().get_file_system_dock().file_removed.connect(_on_file_removed) + + add_tool_menu_item("Create copy of dialogue example balloon...", _copy_dialogue_balloon) + + # Prevent the project from showing as unsaved even though it was only just opened + if Engine.get_physics_frames() == 0: + var timer: Timer = Timer.new() + var suppress_unsaved_marker: Callable + suppress_unsaved_marker = func(): + if Engine.get_frames_per_second() >= 10: + timer.stop() + get_editor_interface().save_all_scenes() + timer.queue_free() + timer.timeout.connect(suppress_unsaved_marker) + add_child(timer) + timer.start(0.1) + + +func _exit_tree() -> void: + remove_autoload_singleton("DialogueManager") + + remove_import_plugin(import_plugin) + import_plugin = null + + remove_translation_parser_plugin(translation_parser_plugin) + translation_parser_plugin = null + + if is_instance_valid(main_view): + main_view.queue_free() + + Engine.remove_meta("DialogueManagerPlugin") + Engine.remove_meta("DialogueCache") + + get_editor_interface().get_file_system_dock().files_moved.disconnect(_on_files_moved) + get_editor_interface().get_file_system_dock().file_removed.disconnect(_on_file_removed) + + remove_tool_menu_item("Create copy of dialogue example balloon...") + + +func _has_main_screen() -> bool: + return true + + +func _make_visible(next_visible: bool) -> void: + if is_instance_valid(main_view): + main_view.visible = next_visible + + +func _get_plugin_name() -> String: + return "Dialogue" + + +func _get_plugin_icon() -> Texture2D: + return load(get_plugin_path() + "/assets/icon.svg") + + +func _handles(object) -> bool: + var editor_settings: EditorSettings = get_editor_interface().get_editor_settings() + var external_editor: String = editor_settings.get_setting("text_editor/external/exec_path") + var use_external_editor: bool = editor_settings.get_setting("text_editor/external/use_external_editor") and external_editor != "" + if object is DialogueResource and use_external_editor and DialogueSettings.get_user_value("open_in_external_editor", false): + var project_path: String = ProjectSettings.globalize_path("res://") + var file_path: String = ProjectSettings.globalize_path(object.resource_path) + OS.create_process(external_editor, [project_path, file_path]) + return false + + return object is DialogueResource + + +func _edit(object) -> void: + if is_instance_valid(main_view) and is_instance_valid(object): + main_view.open_resource(object) + + +func _apply_changes() -> void: + if is_instance_valid(main_view): + main_view.apply_changes() + _update_localization() + + +func _build() -> bool: + # If this is the dotnet Godot then we need to check if the solution file exists + if ProjectSettings.has_setting("dotnet/project/solution_directory"): + var directory: String = ProjectSettings.get("dotnet/project/solution_directory") + var file_name: String = ProjectSettings.get("dotnet/project/assembly_name") + var has_dotnet_solution: bool = FileAccess.file_exists("res://%s/%s.sln" % [directory, file_name]) + DialogueSettings.set_user_value("has_dotnet_solution", has_dotnet_solution) + + # Ignore errors in other files if we are just running the test scene + if DialogueSettings.get_user_value("is_running_test_scene", true): return true + + if dialogue_cache != null: + var files_with_errors = dialogue_cache.get_files_with_errors() + if files_with_errors.size() > 0: + for dialogue_file in files_with_errors: + push_error("You have %d error(s) in %s" % [dialogue_file.errors.size(), dialogue_file.path]) + get_editor_interface().edit_resource(load(files_with_errors[0].path)) + main_view.show_build_error_dialog() + return false + + return true + + +## Get the current version +func get_version() -> String: + var config: ConfigFile = ConfigFile.new() + config.load(get_plugin_path() + "/plugin.cfg") + return config.get_value("plugin", "version") + + +## Get the current path of the plugin +func get_plugin_path() -> String: + return get_script().resource_path.get_base_dir() + + +## Update references to a moved file +func update_import_paths(from_path: String, to_path: String) -> void: + dialogue_cache.move_file_path(from_path, to_path) + + # Reopen the file if it's already open + if main_view.current_file_path == from_path: + if to_path == "": + main_view.close_file(from_path) + else: + main_view.current_file_path = "" + main_view.open_file(to_path) + + # Update any other files that import the moved file + var dependents = dialogue_cache.get_files_with_dependency(from_path) + for dependent in dependents: + dependent.dependencies.remove_at(dependent.dependencies.find(from_path)) + dependent.dependencies.append(to_path) + + # Update the live buffer + if main_view.current_file_path == dependent.path: + main_view.code_edit.text = main_view.code_edit.text.replace(from_path, to_path) + main_view.pristine_text = main_view.code_edit.text + + # Open the file and update the path + var file: FileAccess = FileAccess.open(dependent.path, FileAccess.READ) + var text = file.get_as_text().replace(from_path, to_path) + file.close() + + file = FileAccess.open(dependent.path, FileAccess.WRITE) + file.store_string(text) + file.close() + + +func _update_localization() -> void: + var dialogue_files = dialogue_cache.get_files() + + # Add any new files to POT generation + var files_for_pot: PackedStringArray = ProjectSettings.get_setting("internationalization/locale/translations_pot_files", []) + var files_for_pot_changed: bool = false + for path in dialogue_files: + if not files_for_pot.has(path): + files_for_pot.append(path) + files_for_pot_changed = true + + # Remove any POT references that don't exist any more + for i in range(files_for_pot.size() - 1, -1, -1): + var file_for_pot: String = files_for_pot[i] + if file_for_pot.get_extension() == "dialogue" and not dialogue_files.has(file_for_pot): + files_for_pot.remove_at(i) + files_for_pot_changed = true + + # Update project settings if POT changed + if files_for_pot_changed: + ProjectSettings.set_setting("internationalization/locale/translations_pot_files", files_for_pot) + ProjectSettings.save() + + +### Callbacks + + +func _copy_dialogue_balloon() -> void: + var scale: float = get_editor_interface().get_editor_scale() + var directory_dialog: FileDialog = FileDialog.new() + var label: Label = Label.new() + label.text = "Dialogue balloon files will be copied into chosen directory." + directory_dialog.get_vbox().add_child(label) + directory_dialog.file_mode = FileDialog.FILE_MODE_OPEN_DIR + directory_dialog.min_size = Vector2(600, 500) * scale + directory_dialog.dir_selected.connect(func(path): + var plugin_path: String = get_plugin_path() + + var is_dotnet: bool = DialogueSettings.has_dotnet_solution() + var balloon_path: String = path + ("/Balloon.tscn" if is_dotnet else "/balloon.tscn") + var balloon_script_path: String = path + ("/DialogueBalloon.cs" if is_dotnet else "/balloon.gd") + + # Copy the balloon scene file and change the script reference + var is_small_window: bool = ProjectSettings.get_setting("display/window/size/viewport_width") < 400 + var example_balloon_file_name: String = "small_example_balloon.tscn" if is_small_window else "example_balloon.tscn" + var example_balloon_script_file_name: String = "ExampleBalloon.cs" if is_dotnet else "example_balloon.gd" + var file: FileAccess = FileAccess.open(plugin_path + "/example_balloon/" + example_balloon_file_name, FileAccess.READ) + var file_contents: String = file.get_as_text().replace(plugin_path + "/example_balloon/example_balloon.gd", balloon_script_path) + file = FileAccess.open(balloon_path, FileAccess.WRITE) + file.store_string(file_contents) + file.close() + + # Copy the script file + file = FileAccess.open(plugin_path + "/example_balloon/" + example_balloon_script_file_name, FileAccess.READ) + file_contents = file.get_as_text() + if is_dotnet: + file_contents = file_contents.replace("class ExampleBalloon", "class DialogueBalloon") + file = FileAccess.open(balloon_script_path, FileAccess.WRITE) + file.store_string(file_contents) + file.close() + + get_editor_interface().get_resource_filesystem().scan() + get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", balloon_path) + + DialogueSettings.set_setting("balloon_path", balloon_path) + + directory_dialog.queue_free() + ) + get_editor_interface().get_base_control().add_child(directory_dialog) + directory_dialog.popup_centered() + + +### Signals + + +func _on_files_moved(old_file: String, new_file: String) -> void: + update_import_paths(old_file, new_file) + DialogueSettings.move_recent_file(old_file, new_file) + + +func _on_file_removed(file: String) -> void: + update_import_paths(file, "") + if is_instance_valid(main_view): + main_view.close_file(file) diff --git a/addons/dialogue_manager/settings.gd b/addons/dialogue_manager/settings.gd new file mode 100644 index 0000000..b968a84 --- /dev/null +++ b/addons/dialogue_manager/settings.gd @@ -0,0 +1,184 @@ +@tool +extends Node + + +const DialogueConstants = preload("./constants.gd") + + +### Editor config + +const DEFAULT_SETTINGS = { + states = [], + missing_translations_are_errors = false, + export_characters_in_translation = true, + wrap_lines = false, + new_with_template = true, + include_all_responses = false, + ignore_missing_state_values = false, + custom_test_scene_path = preload("./test_scene.tscn").resource_path, + default_csv_locale = "en", + balloon_path = "", + create_lines_for_responses_with_characters = true, + include_character_in_translation_exports = false, + include_notes_in_translation_exports = false +} + + +static func prepare() -> void: + # Migrate previous keys + for key in [ + "states", + "missing_translations_are_errors", + "export_characters_in_translation", + "wrap_lines", + "new_with_template", + "include_all_responses", + "custom_test_scene_path" + ]: + if ProjectSettings.has_setting("dialogue_manager/%s" % key): + var value = ProjectSettings.get_setting("dialogue_manager/%s" % key) + ProjectSettings.set_setting("dialogue_manager/%s" % key, null) + set_setting(key, value) + + # Set up initial settings + for setting in DEFAULT_SETTINGS: + var setting_name: String = "dialogue_manager/general/%s" % setting + if not ProjectSettings.has_setting(setting_name): + set_setting(setting, DEFAULT_SETTINGS[setting]) + ProjectSettings.set_initial_value(setting_name, DEFAULT_SETTINGS[setting]) + if setting.ends_with("_path"): + ProjectSettings.add_property_info({ + "name": setting_name, + "type": TYPE_STRING, + "hint": PROPERTY_HINT_FILE, + }) + + ProjectSettings.save() + + +static func set_setting(key: String, value) -> void: + ProjectSettings.set_setting("dialogue_manager/general/%s" % key, value) + ProjectSettings.set_initial_value("dialogue_manager/general/%s" % key, DEFAULT_SETTINGS[key]) + ProjectSettings.save() + + +static func get_setting(key: String, default): + if ProjectSettings.has_setting("dialogue_manager/general/%s" % key): + return ProjectSettings.get_setting("dialogue_manager/general/%s" % key) + else: + return default + + +static func get_settings(only_keys: PackedStringArray = []) -> Dictionary: + var settings: Dictionary = {} + for key in DEFAULT_SETTINGS.keys(): + if only_keys.is_empty() or key in only_keys: + settings[key] = get_setting(key, DEFAULT_SETTINGS[key]) + return settings + + +### User config + + +static func get_user_config() -> Dictionary: + var user_config: Dictionary = { + check_for_updates = true, + just_refreshed = null, + recent_files = [], + reopen_files = [], + most_recent_reopen_file = "", + carets = {}, + run_title = "", + run_resource_path = "", + is_running_test_scene = false, + has_dotnet_solution = false, + open_in_external_editor = false + } + + if FileAccess.file_exists(DialogueConstants.USER_CONFIG_PATH): + var file: FileAccess = FileAccess.open(DialogueConstants.USER_CONFIG_PATH, FileAccess.READ) + user_config.merge(JSON.parse_string(file.get_as_text()), true) + + return user_config + + +static func save_user_config(user_config: Dictionary) -> void: + var file: FileAccess = FileAccess.open(DialogueConstants.USER_CONFIG_PATH, FileAccess.WRITE) + file.store_string(JSON.stringify(user_config)) + + +static func set_user_value(key: String, value) -> void: + var user_config: Dictionary = get_user_config() + user_config[key] = value + save_user_config(user_config) + + +static func get_user_value(key: String, default = null): + return get_user_config().get(key, default) + + +static func add_recent_file(path: String) -> void: + var recent_files: Array = get_user_value("recent_files", []) + if path in recent_files: + recent_files.erase(path) + recent_files.insert(0, path) + set_user_value("recent_files", recent_files) + + +static func move_recent_file(from_path: String, to_path: String) -> void: + var recent_files: Array = get_user_value("recent_files", []) + for i in range(0, recent_files.size()): + if recent_files[i] == from_path: + recent_files[i] = to_path + set_user_value("recent_files", recent_files) + + +static func remove_recent_file(path: String) -> void: + var recent_files: Array = get_user_value("recent_files", []) + if path in recent_files: + recent_files.erase(path) + set_user_value("recent_files", recent_files) + + +static func get_recent_files() -> Array: + return get_user_value("recent_files", []) + + +static func clear_recent_files() -> void: + set_user_value("recent_files", []) + set_user_value("carets", {}) + + +static func set_caret(path: String, cursor: Vector2) -> void: + var carets: Dictionary = get_user_value("carets", {}) + carets[path] = { + x = cursor.x, + y = cursor.y + } + set_user_value("carets", carets) + + +static func get_caret(path: String) -> Vector2: + var carets = get_user_value("carets", {}) + if carets.has(path): + var caret = carets.get(path) + return Vector2(caret.x, caret.y) + else: + return Vector2.ZERO + + +static func has_dotnet_solution() -> bool: + if get_user_value("has_dotnet_solution", false): return true + + if ProjectSettings.has_setting("dotnet/project/solution_directory"): + var directory: String = ProjectSettings.get("dotnet/project/solution_directory") + var file_name: String = ProjectSettings.get("dotnet/project/assembly_name") + var has_dotnet_solution: bool = FileAccess.file_exists("res://%s/%s.sln" % [directory, file_name]) + set_user_value("has_dotnet_solution", has_dotnet_solution) + return has_dotnet_solution + else: + var plugin_path: String = new().get_script().resource_path.get_base_dir() + if not ResourceLoader.exists(plugin_path + "/DialogueManager.cs"): return false + if load(plugin_path + "/DialogueManager.cs") == null: return false + + return true diff --git a/addons/dialogue_manager/test_scene.gd b/addons/dialogue_manager/test_scene.gd new file mode 100644 index 0000000..5fc073e --- /dev/null +++ b/addons/dialogue_manager/test_scene.gd @@ -0,0 +1,31 @@ +class_name BaseDialogueTestScene extends Node2D + + +const DialogueSettings = preload("./settings.gd") + + +@onready var title: String = DialogueSettings.get_user_value("run_title") +@onready var resource: DialogueResource = load(DialogueSettings.get_user_value("run_resource_path")) + + +func _ready(): + var screen_index: int = DisplayServer.get_primary_screen() + DisplayServer.window_set_position(Vector2(DisplayServer.screen_get_position(screen_index)) + (DisplayServer.screen_get_size(screen_index) - DisplayServer.window_get_size()) * 0.5) + DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) + + # Normally you can just call DialogueManager directly but doing so before the plugin has been + # enabled in settings will throw a compiler error here so I'm using get_singleton instead. + var dialogue_manager = Engine.get_singleton("DialogueManager") + dialogue_manager.dialogue_ended.connect(_on_dialogue_ended) + dialogue_manager.show_dialogue_balloon(resource, title) + + +func _enter_tree() -> void: + DialogueSettings.set_user_value("is_running_test_scene", false) + + +### Signals + + +func _on_dialogue_ended(_resource: DialogueResource): + get_tree().quit() diff --git a/addons/dialogue_manager/test_scene.tscn b/addons/dialogue_manager/test_scene.tscn new file mode 100644 index 0000000..f2bbd8d --- /dev/null +++ b/addons/dialogue_manager/test_scene.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://addons/dialogue_manager/test_scene.gd" id="1_yupoh"] + + +[node name="TestScene" type="Node2D"] +script = ExtResource("1_yupoh") diff --git a/addons/dialogue_manager/utilities/builtins.gd b/addons/dialogue_manager/utilities/builtins.gd new file mode 100644 index 0000000..f8442d4 --- /dev/null +++ b/addons/dialogue_manager/utilities/builtins.gd @@ -0,0 +1,468 @@ +extends Object + + +const DialogueConstants = preload("../constants.gd") + +const SUPPORTED_BUILTIN_TYPES = [ + TYPE_ARRAY, + TYPE_VECTOR2, + TYPE_VECTOR3, + TYPE_VECTOR4, + TYPE_DICTIONARY, + TYPE_QUATERNION, + TYPE_COLOR, + TYPE_SIGNAL +] + + +static var resolve_method_error: Error = OK + + +static func is_supported(thing) -> bool: + return typeof(thing) in SUPPORTED_BUILTIN_TYPES + + +static func resolve_property(builtin, property: String): + match typeof(builtin): + TYPE_ARRAY, TYPE_DICTIONARY, TYPE_QUATERNION: + return builtin[property] + + # Some types have constants that we need to manually resolve + + TYPE_VECTOR2: + return resolve_vector2_property(builtin, property) + TYPE_VECTOR3: + return resolve_vector3_property(builtin, property) + TYPE_VECTOR4: + return resolve_vector4_property(builtin, property) + TYPE_COLOR: + return resolve_color_property(builtin, property) + + +static func resolve_method(thing, method_name: String, args: Array): + resolve_method_error = OK + + # Resolve static methods manually + match typeof(thing): + TYPE_VECTOR2: + match method_name: + "from_angle": + return Vector2.from_angle(args[0]) + + TYPE_COLOR: + match method_name: + "from_hsv": + return Color.from_hsv(args[0], args[1], args[2]) if args.size() == 3 else Color.from_hsv(args[0], args[1], args[2], args[3]) + "from_ok_hsl": + return Color.from_ok_hsl(args[0], args[1], args[2]) if args.size() == 3 else Color.from_ok_hsl(args[0], args[1], args[2], args[3]) + "from_rgbe9995": + return Color.from_rgbe9995(args[0]) + "from_string": + return Color.from_string(args[0], args[1]) + + TYPE_QUATERNION: + match method_name: + "from_euler": + return Quaternion.from_euler(args[0]) + + # Anything else can be evaulatated automatically + var references: Array = ["thing"] + for i in range(0, args.size()): + references.append("arg%d" % i) + var expression = Expression.new() + if expression.parse("thing.%s(%s)" % [method_name, ",".join(references.slice(1))], references) != OK: + assert(false, expression.get_error_text()) + var result = expression.execute([thing] + args, null, false) + if expression.has_execute_failed(): + resolve_method_error = ERR_CANT_RESOLVE + return null + + return result + + +static func has_resolve_method_failed() -> bool: + return resolve_method_error != OK + + +static func resolve_color_property(color: Color, property: String): + match property: + "ALICE_BLUE": + return Color.ALICE_BLUE + "ANTIQUE_WHITE": + return Color.ANTIQUE_WHITE + "AQUA": + return Color.AQUA + "AQUAMARINE": + return Color.AQUAMARINE + "AZURE": + return Color.AZURE + "BEIGE": + return Color.BEIGE + "BISQUE": + return Color.BISQUE + "BLACK": + return Color.BLACK + "BLANCHED_ALMOND": + return Color.BLANCHED_ALMOND + "BLUE": + return Color.BLUE + "BLUE_VIOLET": + return Color.BLUE_VIOLET + "BROWN": + return Color.BROWN + "BURLYWOOD": + return Color.BURLYWOOD + "CADET_BLUE": + return Color.CADET_BLUE + "CHARTREUSE": + return Color.CHARTREUSE + "CHOCOLATE": + return Color.CHOCOLATE + "CORAL": + return Color.CORAL + "CORNFLOWER_BLUE": + return Color.CORNFLOWER_BLUE + "CORNSILK": + return Color.CORNSILK + "CRIMSON": + return Color.CRIMSON + "CYAN": + return Color.CYAN + "DARK_BLUE": + return Color.DARK_BLUE + "DARK_CYAN": + return Color.DARK_CYAN + "DARK_GOLDENROD": + return Color.DARK_GOLDENROD + "DARK_GRAY": + return Color.DARK_GRAY + "DARK_GREEN": + return Color.DARK_GREEN + "DARK_KHAKI": + return Color.DARK_KHAKI + "DARK_MAGENTA": + return Color.DARK_MAGENTA + "DARK_OLIVE_GREEN": + return Color.DARK_OLIVE_GREEN + "DARK_ORANGE": + return Color.DARK_ORANGE + "DARK_ORCHID": + return Color.DARK_ORCHID + "DARK_RED": + return Color.DARK_RED + "DARK_SALMON": + return Color.DARK_SALMON + "DARK_SEA_GREEN": + return Color.DARK_SEA_GREEN + "DARK_SLATE_BLUE": + return Color.DARK_SLATE_BLUE + "DARK_SLATE_GRAY": + return Color.DARK_SLATE_GRAY + "DARK_TURQUOISE": + return Color.DARK_TURQUOISE + "DARK_VIOLET": + return Color.DARK_VIOLET + "DEEP_PINK": + return Color.DEEP_PINK + "DEEP_SKY_BLUE": + return Color.DEEP_SKY_BLUE + "DIM_GRAY": + return Color.DIM_GRAY + "DODGER_BLUE": + return Color.DODGER_BLUE + "FIREBRICK": + return Color.FIREBRICK + "FLORAL_WHITE": + return Color.FLORAL_WHITE + "FOREST_GREEN": + return Color.FOREST_GREEN + "FUCHSIA": + return Color.FUCHSIA + "GAINSBORO": + return Color.GAINSBORO + "GHOST_WHITE": + return Color.GHOST_WHITE + "GOLD": + return Color.GOLD + "GOLDENROD": + return Color.GOLDENROD + "GRAY": + return Color.GRAY + "GREEN": + return Color.GREEN + "GREEN_YELLOW": + return Color.GREEN_YELLOW + "HONEYDEW": + return Color.HONEYDEW + "HOT_PINK": + return Color.HOT_PINK + "INDIAN_RED": + return Color.INDIAN_RED + "INDIGO": + return Color.INDIGO + "IVORY": + return Color.IVORY + "KHAKI": + return Color.KHAKI + "LAVENDER": + return Color.LAVENDER + "LAVENDER_BLUSH": + return Color.LAVENDER_BLUSH + "LAWN_GREEN": + return Color.LAWN_GREEN + "LEMON_CHIFFON": + return Color.LEMON_CHIFFON + "LIGHT_BLUE": + return Color.LIGHT_BLUE + "LIGHT_CORAL": + return Color.LIGHT_CORAL + "LIGHT_CYAN": + return Color.LIGHT_CYAN + "LIGHT_GOLDENROD": + return Color.LIGHT_GOLDENROD + "LIGHT_GRAY": + return Color.LIGHT_GRAY + "LIGHT_GREEN": + return Color.LIGHT_GREEN + "LIGHT_PINK": + return Color.LIGHT_PINK + "LIGHT_SALMON": + return Color.LIGHT_SALMON + "LIGHT_SEA_GREEN": + return Color.LIGHT_SEA_GREEN + "LIGHT_SKY_BLUE": + return Color.LIGHT_SKY_BLUE + "LIGHT_SLATE_GRAY": + return Color.LIGHT_SLATE_GRAY + "LIGHT_STEEL_BLUE": + return Color.LIGHT_STEEL_BLUE + "LIGHT_YELLOW": + return Color.LIGHT_YELLOW + "LIME": + return Color.LIME + "LIME_GREEN": + return Color.LIME_GREEN + "LINEN": + return Color.LINEN + "MAGENTA": + return Color.MAGENTA + "MAROON": + return Color.MAROON + "MEDIUM_AQUAMARINE": + return Color.MEDIUM_AQUAMARINE + "MEDIUM_BLUE": + return Color.MEDIUM_BLUE + "MEDIUM_ORCHID": + return Color.MEDIUM_ORCHID + "MEDIUM_PURPLE": + return Color.MEDIUM_PURPLE + "MEDIUM_SEA_GREEN": + return Color.MEDIUM_SEA_GREEN + "MEDIUM_SLATE_BLUE": + return Color.MEDIUM_SLATE_BLUE + "MEDIUM_SPRING_GREEN": + return Color.MEDIUM_SPRING_GREEN + "MEDIUM_TURQUOISE": + return Color.MEDIUM_TURQUOISE + "MEDIUM_VIOLET_RED": + return Color.MEDIUM_VIOLET_RED + "MIDNIGHT_BLUE": + return Color.MIDNIGHT_BLUE + "MINT_CREAM": + return Color.MINT_CREAM + "MISTY_ROSE": + return Color.MISTY_ROSE + "MOCCASIN": + return Color.MOCCASIN + "NAVAJO_WHITE": + return Color.NAVAJO_WHITE + "NAVY_BLUE": + return Color.NAVY_BLUE + "OLD_LACE": + return Color.OLD_LACE + "OLIVE": + return Color.OLIVE + "OLIVE_DRAB": + return Color.OLIVE_DRAB + "ORANGE": + return Color.ORANGE + "ORANGE_RED": + return Color.ORANGE_RED + "ORCHID": + return Color.ORCHID + "PALE_GOLDENROD": + return Color.PALE_GOLDENROD + "PALE_GREEN": + return Color.PALE_GREEN + "PALE_TURQUOISE": + return Color.PALE_TURQUOISE + "PALE_VIOLET_RED": + return Color.PALE_VIOLET_RED + "PAPAYA_WHIP": + return Color.PAPAYA_WHIP + "PEACH_PUFF": + return Color.PEACH_PUFF + "PERU": + return Color.PERU + "PINK": + return Color.PINK + "PLUM": + return Color.PLUM + "POWDER_BLUE": + return Color.POWDER_BLUE + "PURPLE": + return Color.PURPLE + "REBECCA_PURPLE": + return Color.REBECCA_PURPLE + "RED": + return Color.RED + "ROSY_BROWN": + return Color.ROSY_BROWN + "ROYAL_BLUE": + return Color.ROYAL_BLUE + "SADDLE_BROWN": + return Color.SADDLE_BROWN + "SALMON": + return Color.SALMON + "SANDY_BROWN": + return Color.SANDY_BROWN + "SEA_GREEN": + return Color.SEA_GREEN + "SEASHELL": + return Color.SEASHELL + "SIENNA": + return Color.SIENNA + "SILVER": + return Color.SILVER + "SKY_BLUE": + return Color.SKY_BLUE + "SLATE_BLUE": + return Color.SLATE_BLUE + "SLATE_GRAY": + return Color.SLATE_GRAY + "SNOW": + return Color.SNOW + "SPRING_GREEN": + return Color.SPRING_GREEN + "STEEL_BLUE": + return Color.STEEL_BLUE + "TAN": + return Color.TAN + "TEAL": + return Color.TEAL + "THISTLE": + return Color.THISTLE + "TOMATO": + return Color.TOMATO + "TRANSPARENT": + return Color.TRANSPARENT + "TURQUOISE": + return Color.TURQUOISE + "VIOLET": + return Color.VIOLET + "WEB_GRAY": + return Color.WEB_GRAY + "WEB_GREEN": + return Color.WEB_GREEN + "WEB_MAROON": + return Color.WEB_MAROON + "WEB_PURPLE": + return Color.WEB_PURPLE + "WHEAT": + return Color.WHEAT + "WHITE": + return Color.WHITE + "WHITE_SMOKE": + return Color.WHITE_SMOKE + "YELLOW": + return Color.YELLOW + "YELLOW_GREEN": + return Color.YELLOW_GREEN + + return color[property] + + +static func resolve_vector2_property(vector: Vector2, property: String): + match property: + "AXIS_X": + return Vector2.AXIS_X + "AXIS_Y": + return Vector2.AXIS_Y + "ZERO": + return Vector2.ZERO + "ONE": + return Vector2.ONE + "INF": + return Vector2.INF + "LEFT": + return Vector2.LEFT + "RIGHT": + return Vector2.RIGHT + "UP": + return Vector2.UP + "DOWN": + return Vector2.DOWN + + return vector[property] + + +static func resolve_vector3_property(vector: Vector3, property: String): + match property: + "AXIS_X": + return Vector3.AXIS_X + "AXIS_Y": + return Vector3.AXIS_Y + "AXIS_Z": + return Vector3.AXIS_Z + "ZERO": + return Vector3.ZERO + "ONE": + return Vector3.ONE + "INF": + return Vector3.INF + "LEFT": + return Vector3.LEFT + "RIGHT": + return Vector3.RIGHT + "UP": + return Vector3.UP + "DOWN": + return Vector3.DOWN + "FORWARD": + return Vector3.FORWARD + "BACK": + return Vector3.BACK + "MODEL_LEFT": + return Vector3(1, 0, 0) + "MODEL_RIGHT": + return Vector3(-1, 0, 0) + "MODEL_TOP": + return Vector3(0, 1, 0) + "MODEL_BOTTOM": + return Vector3(0, -1, 0) + "MODEL_FRONT": + return Vector3(0, 0, 1) + "MODEL_REAR": + return Vector3(0, 0, -1) + + return vector[property] + + +static func resolve_vector4_property(vector: Vector4, property: String): + match property: + "AXIS_X": + return Vector4.AXIS_X + "AXIS_Y": + return Vector4.AXIS_Y + "AXIS_Z": + return Vector4.AXIS_Z + "AXIS_W": + return Vector4.AXIS_W + "ZERO": + return Vector4.ZERO + "ONE": + return Vector4.ONE + "INF": + return Vector4.INF + + return vector[property] diff --git a/addons/dialogue_manager/views/main_view.gd b/addons/dialogue_manager/views/main_view.gd new file mode 100644 index 0000000..445d53d --- /dev/null +++ b/addons/dialogue_manager/views/main_view.gd @@ -0,0 +1,1100 @@ +@tool +extends Control + + +const DialogueConstants = preload("../constants.gd") +const DialogueSettings = preload("../settings.gd") + +const OPEN_OPEN = 100 +const OPEN_CLEAR = 101 + +const TRANSLATIONS_GENERATE_LINE_IDS = 100 +const TRANSLATIONS_SAVE_CHARACTERS_TO_CSV = 201 +const TRANSLATIONS_SAVE_TO_CSV = 202 +const TRANSLATIONS_IMPORT_FROM_CSV = 203 + +const ITEM_SAVE = 100 +const ITEM_SAVE_AS = 101 +const ITEM_CLOSE = 102 +const ITEM_CLOSE_ALL = 103 +const ITEM_CLOSE_OTHERS = 104 +const ITEM_COPY_PATH = 200 +const ITEM_SHOW_IN_FILESYSTEM = 201 + +enum TranslationSource { + CharacterNames, + Lines +} + + +@onready var parse_timer := $ParseTimer + +# Dialogs +@onready var new_dialog: FileDialog = $NewDialog +@onready var save_dialog: FileDialog = $SaveDialog +@onready var open_dialog: FileDialog = $OpenDialog +@onready var export_dialog: FileDialog = $ExportDialog +@onready var import_dialog: FileDialog = $ImportDialog +@onready var errors_dialog: AcceptDialog = $ErrorsDialog +@onready var settings_dialog: AcceptDialog = $SettingsDialog +@onready var settings_view := $SettingsDialog/SettingsView +@onready var build_error_dialog: AcceptDialog = $BuildErrorDialog +@onready var close_confirmation_dialog: ConfirmationDialog = $CloseConfirmationDialog +@onready var updated_dialog: AcceptDialog = $UpdatedDialog +@onready var find_in_files_dialog: AcceptDialog = $FindInFilesDialog +@onready var find_in_files: Control = $FindInFilesDialog/FindInFiles + +# Toolbar +@onready var new_button: Button = %NewButton +@onready var open_button: MenuButton = %OpenButton +@onready var save_all_button: Button = %SaveAllButton +@onready var find_in_files_button: Button = %FindInFilesButton +@onready var test_button: Button = %TestButton +@onready var search_button: Button = %SearchButton +@onready var insert_button: MenuButton = %InsertButton +@onready var translations_button: MenuButton = %TranslationsButton +@onready var settings_button: Button = %SettingsButton +@onready var support_button: Button = %SupportButton +@onready var docs_button: Button = %DocsButton +@onready var version_label: Label = %VersionLabel +@onready var update_button: Button = %UpdateButton + +@onready var search_and_replace := %SearchAndReplace + +# Code editor +@onready var content: HSplitContainer = %Content +@onready var files_list := %FilesList +@onready var files_popup_menu: PopupMenu = %FilesPopupMenu +@onready var title_list := %TitleList +@onready var code_edit := %CodeEdit +@onready var errors_panel := %ErrorsPanel + +# The Dialogue Manager plugin +var editor_plugin: EditorPlugin + +# The currently open file +var current_file_path: String = "": + set(next_current_file_path): + current_file_path = next_current_file_path + files_list.current_file_path = current_file_path + if current_file_path == "": + save_all_button.disabled = true + test_button.disabled = true + search_button.disabled = true + insert_button.disabled = true + translations_button.disabled = true + content.dragger_visibility = SplitContainer.DRAGGER_HIDDEN + files_list.hide() + title_list.hide() + code_edit.hide() + errors_panel.hide() + else: + test_button.disabled = false + search_button.disabled = false + insert_button.disabled = false + translations_button.disabled = false + content.dragger_visibility = SplitContainer.DRAGGER_VISIBLE + files_list.show() + title_list.show() + code_edit.show() + + code_edit.text = open_buffers[current_file_path].text + code_edit.errors = [] + code_edit.clear_undo_history() + code_edit.set_cursor(DialogueSettings.get_caret(current_file_path)) + code_edit.grab_focus() + + _on_code_edit_text_changed() + + errors_panel.errors = [] + code_edit.errors = [] + get: + return current_file_path + +# A reference to the currently open files and their last saved text +var open_buffers: Dictionary = {} + +# Which thing are we exporting translations for? +var translation_source: TranslationSource = TranslationSource.Lines + + +func _ready() -> void: + apply_theme() + + # Start with nothing open + self.current_file_path = "" + + # Set up the update checker + version_label.text = "v%s" % editor_plugin.get_version() + update_button.editor_plugin = editor_plugin + update_button.on_before_refresh = func on_before_refresh(): + # Save everything + DialogueSettings.set_user_value("just_refreshed", { + current_file_path = current_file_path, + open_buffers = open_buffers + }) + return true + + # Did we just load from an addon version refresh? + var just_refreshed = DialogueSettings.get_user_value("just_refreshed", null) + if just_refreshed != null: + DialogueSettings.set_user_value("just_refreshed", null) + call_deferred("load_from_version_refresh", just_refreshed) + + # Hook up the search toolbar + search_and_replace.code_edit = code_edit + + # Connect menu buttons + insert_button.get_popup().id_pressed.connect(_on_insert_button_menu_id_pressed) + translations_button.get_popup().id_pressed.connect(_on_translations_button_menu_id_pressed) + + code_edit.main_view = self + code_edit.wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY if DialogueSettings.get_setting("wrap_lines", false) else TextEdit.LINE_WRAPPING_NONE + var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() + editor_settings.settings_changed.connect(_on_editor_settings_changed) + _on_editor_settings_changed() + + # Reopen any files that were open when Godot was closed + if editor_settings.get_setting("text_editor/behavior/files/restore_scripts_on_load"): + var reopen_files: Array = DialogueSettings.get_user_value("reopen_files", []) + for reopen_file in reopen_files: + open_file(reopen_file) + + self.current_file_path = DialogueSettings.get_user_value("most_recent_reopen_file", "") + + save_all_button.disabled = true + + close_confirmation_dialog.ok_button_text = DialogueConstants.translate(&"confirm_close.save") + close_confirmation_dialog.add_button(DialogueConstants.translate(&"confirm_close.discard"), true, "discard") + + settings_view.editor_plugin = editor_plugin + + errors_dialog.dialog_text = DialogueConstants.translate(&"errors_in_script") + + +func _exit_tree() -> void: + DialogueSettings.set_user_value("reopen_files", open_buffers.keys()) + DialogueSettings.set_user_value("most_recent_reopen_file", self.current_file_path) + + +func _unhandled_input(event: InputEvent) -> void: + if not visible: return + + if event is InputEventKey and event.is_pressed(): + match event.as_text(): + "Ctrl+Alt+S", "Command+Alt+S": + get_viewport().set_input_as_handled() + save_file(current_file_path) + "Ctrl+W", "Command+W": + get_viewport().set_input_as_handled() + close_file(current_file_path) + "Ctrl+F5", "Command+F5": + get_viewport().set_input_as_handled() + _on_test_button_pressed() + "Ctrl+Shift+F", "Command+Shift+F": + get_viewport().set_input_as_handled() + _on_find_in_files_button_pressed() + + +func apply_changes() -> void: + save_files() + + +# Load back to the previous buffer regardless of if it was actually saved +func load_from_version_refresh(just_refreshed: Dictionary) -> void: + if just_refreshed.has("current_file_content"): + # We just loaded from a version before multiple buffers + var file: FileAccess = FileAccess.open(just_refreshed.current_file_path, FileAccess.READ) + var file_text: String = file.get_as_text() + open_buffers[just_refreshed.current_file_path] = { + pristine_text = file_text, + text = just_refreshed.current_file_content + } + else: + open_buffers = just_refreshed.open_buffers + + if just_refreshed.current_file_path != "": + editor_plugin.get_editor_interface().edit_resource(load(just_refreshed.current_file_path)) + else: + editor_plugin.get_editor_interface().set_main_screen_editor("Dialogue") + + updated_dialog.dialog_text = DialogueConstants.translate(&"update.success").format({ version = update_button.get_version() }) + updated_dialog.popup_centered() + + +func new_file(path: String, content: String = "") -> void: + if open_buffers.has(path): + remove_file_from_open_buffers(path) + + var file: FileAccess = FileAccess.open(path, FileAccess.WRITE) + if content == "": + if DialogueSettings.get_setting("new_with_template", true): + file.store_string("\n".join([ + "~ this_is_a_node_title", + "", + "Nathan: [[Hi|Hello|Howdy]], this is some dialogue.", + "Nathan: Here are some choices.", + "- First one", + "\tNathan: You picked the first one.", + "- Second one", + "\tNathan: You picked the second one.", + "- Start again => this_is_a_node_title", + "- End the conversation => END", + "Nathan: For more information see the online documentation.", + "", + "=> END" + ])) + else: + file.store_string(content) + + editor_plugin.get_editor_interface().get_resource_filesystem().scan() + + +# Open a dialogue resource for editing +func open_resource(resource: DialogueResource) -> void: + open_file(resource.resource_path) + + +func open_file(path: String) -> void: + if not open_buffers.has(path): + var file: FileAccess = FileAccess.open(path, FileAccess.READ) + var text = file.get_as_text() + + open_buffers[path] = { + cursor = Vector2.ZERO, + text = text, + pristine_text = text + } + + DialogueSettings.add_recent_file(path) + build_open_menu() + + files_list.files = open_buffers.keys() + files_list.select_file(path) + + self.current_file_path = path + + +func show_file_in_filesystem(path: String) -> void: + var file_system_dock: FileSystemDock = Engine.get_meta("DialogueManagerPlugin") \ + .get_editor_interface() \ + .get_file_system_dock() + + file_system_dock.navigate_to_path(path) + + +# Save any open files +func save_files() -> void: + save_all_button.disabled = true + + var saved_files: PackedStringArray = [] + for path in open_buffers: + if open_buffers[path].text != open_buffers[path].pristine_text: + saved_files.append(path) + save_file(path, false) + + if saved_files.size() > 0: + Engine.get_meta("DialogueCache").reimport_files(saved_files) + + +# Save a file +func save_file(path: String, rescan_file_system: bool = true) -> void: + var buffer = open_buffers[path] + + files_list.mark_file_as_unsaved(path, false) + save_all_button.disabled = files_list.unsaved_files.size() == 0 + + # Don't bother saving if there is nothing to save + if buffer.text == buffer.pristine_text: + return + + buffer.pristine_text = buffer.text + + # Save the current text + var file: FileAccess = FileAccess.open(path, FileAccess.WRITE) + file.store_string(buffer.text) + file.close() + + if rescan_file_system: + Engine.get_meta("DialogueManagerPlugin") \ + .get_editor_interface() \ + .get_resource_filesystem()\ + .scan() + + +func close_file(file: String) -> void: + if not file in open_buffers.keys(): return + + var buffer = open_buffers[file] + + if buffer.text == buffer.pristine_text: + remove_file_from_open_buffers(file) + else: + close_confirmation_dialog.dialog_text = DialogueConstants.translate(&"confirm_close").format({ path = file.get_file() }) + close_confirmation_dialog.popup_centered() + + +func remove_file_from_open_buffers(file: String) -> void: + if not file in open_buffers.keys(): return + + var current_index = open_buffers.keys().find(file) + + open_buffers.erase(file) + if open_buffers.size() == 0: + self.current_file_path = "" + else: + current_index = clamp(current_index, 0, open_buffers.size() - 1) + self.current_file_path = open_buffers.keys()[current_index] + files_list.files = open_buffers.keys() + + +# Apply theme colors and icons to the UI +func apply_theme() -> void: + if is_instance_valid(editor_plugin) and is_instance_valid(code_edit): + var scale: float = editor_plugin.get_editor_interface().get_editor_scale() + var editor_settings = editor_plugin.get_editor_interface().get_editor_settings() + code_edit.theme_overrides = { + scale = scale, + + background_color = editor_settings.get_setting("text_editor/theme/highlighting/background_color"), + current_line_color = editor_settings.get_setting("text_editor/theme/highlighting/current_line_color"), + error_line_color = editor_settings.get_setting("text_editor/theme/highlighting/mark_color"), + + critical_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_markers/critical_color"), + notice_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_markers/notice_color"), + + titles_color = editor_settings.get_setting("text_editor/theme/highlighting/control_flow_keyword_color"), + text_color = editor_settings.get_setting("text_editor/theme/highlighting/text_color"), + conditions_color = editor_settings.get_setting("text_editor/theme/highlighting/keyword_color"), + mutations_color = editor_settings.get_setting("text_editor/theme/highlighting/function_color"), + members_color = editor_settings.get_setting("text_editor/theme/highlighting/member_variable_color"), + strings_color = editor_settings.get_setting("text_editor/theme/highlighting/string_color"), + numbers_color = editor_settings.get_setting("text_editor/theme/highlighting/number_color"), + symbols_color = editor_settings.get_setting("text_editor/theme/highlighting/symbol_color"), + comments_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_color"), + jumps_color = Color(editor_settings.get_setting("text_editor/theme/highlighting/control_flow_keyword_color"), 0.7), + + font_size = editor_settings.get_setting("interface/editor/code_font_size") + } + + new_button.icon = get_theme_icon("New", "EditorIcons") + new_button.tooltip_text = DialogueConstants.translate(&"start_a_new_file") + + open_button.icon = get_theme_icon("Load", "EditorIcons") + open_button.tooltip_text = DialogueConstants.translate(&"open_a_file") + + save_all_button.icon = get_theme_icon("Save", "EditorIcons") + save_all_button.tooltip_text = DialogueConstants.translate(&"start_all_files") + + find_in_files_button.icon = get_theme_icon("ViewportZoom", "EditorIcons") + find_in_files_button.tooltip_text = DialogueConstants.translate(&"find_in_files") + + test_button.icon = get_theme_icon("PlayScene", "EditorIcons") + test_button.tooltip_text = DialogueConstants.translate(&"test_dialogue") + + search_button.icon = get_theme_icon("Search", "EditorIcons") + search_button.tooltip_text = DialogueConstants.translate(&"search_for_text") + + insert_button.icon = get_theme_icon("RichTextEffect", "EditorIcons") + insert_button.text = DialogueConstants.translate(&"insert") + + translations_button.icon = get_theme_icon("Translation", "EditorIcons") + translations_button.text = DialogueConstants.translate(&"translations") + + settings_button.icon = get_theme_icon("Tools", "EditorIcons") + settings_button.tooltip_text = DialogueConstants.translate(&"settings") + + support_button.icon = get_theme_icon("Heart", "EditorIcons") + support_button.text = DialogueConstants.translate(&"sponsor") + support_button.tooltip_text = DialogueConstants.translate(&"show_support") + + docs_button.icon = get_theme_icon("Help", "EditorIcons") + docs_button.text = DialogueConstants.translate(&"docs") + + update_button.apply_theme() + + # Set up the effect menu + var popup: PopupMenu = insert_button.get_popup() + popup.clear() + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.wave_bbcode"), 0) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.shake_bbcode"), 1) + popup.add_separator() + popup.add_icon_item(get_theme_icon("Time", "EditorIcons"), DialogueConstants.translate(&"insert.typing_pause"), 3) + popup.add_icon_item(get_theme_icon("ViewportSpeed", "EditorIcons"), DialogueConstants.translate(&"insert.typing_speed_change"), 4) + popup.add_icon_item(get_theme_icon("DebugNext", "EditorIcons"), DialogueConstants.translate(&"insert.auto_advance"), 5) + popup.add_separator(DialogueConstants.translate(&"insert.templates")) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.title"), 6) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.dialogue"), 7) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.response"), 8) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.random_lines"), 9) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.random_text"), 10) + popup.add_separator(DialogueConstants.translate(&"insert.actions")) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.jump"), 11) + popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.end_dialogue"), 12) + + # Set up the translations menu + popup = translations_button.get_popup() + popup.clear() + popup.add_icon_item(get_theme_icon("Translation", "EditorIcons"), DialogueConstants.translate(&"generate_line_ids"), TRANSLATIONS_GENERATE_LINE_IDS) + popup.add_separator() + popup.add_icon_item(get_theme_icon("FileList", "EditorIcons"), DialogueConstants.translate(&"save_characters_to_csv"), TRANSLATIONS_SAVE_CHARACTERS_TO_CSV) + popup.add_icon_item(get_theme_icon("FileList", "EditorIcons"), DialogueConstants.translate(&"save_to_csv"), TRANSLATIONS_SAVE_TO_CSV) + popup.add_icon_item(get_theme_icon("AssetLib", "EditorIcons"), DialogueConstants.translate(&"import_from_csv"), TRANSLATIONS_IMPORT_FROM_CSV) + + # Dialog sizes + new_dialog.min_size = Vector2(600, 500) * scale + save_dialog.min_size = Vector2(600, 500) * scale + open_dialog.min_size = Vector2(600, 500) * scale + export_dialog.min_size = Vector2(600, 500) * scale + import_dialog.min_size = Vector2(600, 500) * scale + settings_dialog.min_size = Vector2(1000, 600) * scale + settings_dialog.max_size = Vector2(1000, 600) * scale + find_in_files_dialog.min_size = Vector2(800, 600) * scale + + +### Helpers + + +# Refresh the open menu with the latest files +func build_open_menu() -> void: + var menu = open_button.get_popup() + menu.clear() + menu.add_icon_item(get_theme_icon("Load", "EditorIcons"), DialogueConstants.translate(&"open.open"), OPEN_OPEN) + menu.add_separator() + + var recent_files = DialogueSettings.get_recent_files() + if recent_files.size() == 0: + menu.add_item(DialogueConstants.translate(&"open.no_recent_files")) + menu.set_item_disabled(2, true) + else: + for path in recent_files: + if FileAccess.file_exists(path): + menu.add_icon_item(get_theme_icon("File", "EditorIcons"), path) + + menu.add_separator() + menu.add_item(DialogueConstants.translate(&"open.clear_recent_files"), OPEN_CLEAR) + if menu.id_pressed.is_connected(_on_open_menu_id_pressed): + menu.id_pressed.disconnect(_on_open_menu_id_pressed) + menu.id_pressed.connect(_on_open_menu_id_pressed) + + +# Get the last place a CSV, etc was exported +func get_last_export_path(extension: String) -> String: + var filename = current_file_path.get_file().replace(".dialogue", "." + extension) + return DialogueSettings.get_user_value("last_export_path", current_file_path.get_base_dir()) + "/" + filename + + +# Check the current text for errors +func parse() -> void: + # Skip if nothing to parse + if current_file_path == "": return + + var parser = DialogueManagerParser.new() + var errors: Array[Dictionary] = [] + if parser.parse(code_edit.text, current_file_path) != OK: + errors = parser.get_errors() + code_edit.errors = errors + errors_panel.errors = errors + parser.free() + + +func show_build_error_dialog() -> void: + build_error_dialog.dialog_text = DialogueConstants.translate(&"errors_with_build") + build_error_dialog.popup_centered() + + +# Generate translation line IDs for any line that doesn't already have one +func generate_translations_keys() -> void: + randomize() + seed(Time.get_unix_time_from_system()) + + var parser = DialogueManagerParser.new() + + var cursor: Vector2 = code_edit.get_cursor() + var lines: PackedStringArray = code_edit.text.split("\n") + + var key_regex = RegEx.new() + key_regex.compile("\\[ID:(?<key>.*?)\\]") + + # Make list of known keys + var known_keys = {} + for i in range(0, lines.size()): + var line = lines[i] + var found = key_regex.search(line) + if found: + var text = "" + var l = line.replace(found.strings[0], "").strip_edges().strip_edges() + if l.begins_with("- "): + text = parser.extract_response_prompt(l) + elif ":" in l: + text = l.split(":")[1] + else: + text = l + known_keys[found.strings[found.names.get("key")]] = text + + # Add in any that are missing + for i in lines.size(): + var line = lines[i] + var l = line.strip_edges() + + if parser.is_line_empty(l): continue + if parser.is_condition_line(l, true): continue + if parser.is_title_line(l): continue + if parser.is_mutation_line(l): continue + if parser.is_goto_line(l): continue + if parser.is_import_line(l): continue + + if "[ID:" in line: continue + + var key = "t" + str(randi() % 1000000).sha1_text().substr(0, 10) + while key in known_keys: + key = "t" + str(randi() % 1000000).sha1_text().substr(0, 10) + + var text = "" + if l.begins_with("- "): + text = parser.extract_response_prompt(l) + else: + text = l.substr(l.find(":") + 1) + + lines[i] = line.replace(text, text + " [ID:%s]" % key) + known_keys[key] = text + + code_edit.text = "\n".join(lines) + code_edit.set_cursor(cursor) + _on_code_edit_text_changed() + + parser.free() + + +# Add a translation file to the project settings +func add_path_to_project_translations(path: String) -> void: + var translations: PackedStringArray = ProjectSettings.get_setting("internationalization/locale/translations") + if not path in translations: + translations.append(path) + ProjectSettings.save() + + +# Export dialogue and responses to CSV +func export_translations_to_csv(path: String) -> void: + var default_locale: String = DialogueSettings.get_setting("default_csv_locale", "en") + + var file: FileAccess + + # If the file exists, open it first and work out which keys are already in it + var existing_csv: Dictionary = {} + var column_count: int = 2 + var default_locale_column: int = 1 + var character_column: int = -1 + var notes_column: int = -1 + if FileAccess.file_exists(path): + file = FileAccess.open(path, FileAccess.READ) + var is_first_line = true + var line: Array + while !file.eof_reached(): + line = file.get_csv_line() + if is_first_line: + is_first_line = false + column_count = line.size() + for i in range(1, line.size()): + if line[i] == default_locale: + default_locale_column = i + elif line[i] == "_character": + character_column = i + elif line[i] == "_notes": + notes_column = i + + # Make sure the line isn't empty before adding it + if line.size() > 0 and line[0].strip_edges() != "": + existing_csv[line[0]] = line + + # The character column wasn't found in the existing file but the setting is turned on + if character_column == -1 and DialogueSettings.get_setting("include_character_in_translation_exports", false): + character_column = column_count + column_count += 1 + existing_csv["keys"].append("_character") + + # The notes column wasn't found in the existing file but the setting is turned on + if notes_column == -1 and DialogueSettings.get_setting("include_notes_in_translation_exports", false): + notes_column = column_count + column_count += 1 + existing_csv["keys"].append("_notes") + + # Start a new file + file = FileAccess.open(path, FileAccess.WRITE) + + if not FileAccess.file_exists(path): + var headings: PackedStringArray = ["keys", default_locale] + if DialogueSettings.get_setting("include_character_in_translation_exports", false): + character_column = headings.size() + headings.append("_character") + if DialogueSettings.get_setting("include_notes_in_translation_exports", false): + notes_column = headings.size() + headings.append("_notes") + file.store_csv_line(headings) + column_count = headings.size() + + # Write our translations to file + var known_keys: PackedStringArray = [] + + var dialogue: Dictionary = DialogueManagerParser.parse_string(code_edit.text, current_file_path).lines + + # Make a list of stuff that needs to go into the file + var lines_to_save = [] + for key in dialogue.keys(): + var line: Dictionary = dialogue.get(key) + + if not line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: continue + if line.translation_key in known_keys: continue + + known_keys.append(line.translation_key) + + var line_to_save: PackedStringArray = [] + if existing_csv.has(line.translation_key): + line_to_save = existing_csv.get(line.translation_key) + line_to_save.resize(column_count) + existing_csv.erase(line.translation_key) + else: + line_to_save.resize(column_count) + line_to_save[0] = line.translation_key + + line_to_save[default_locale_column] = line.text + if character_column > -1: + line_to_save[character_column] = "(response)" if line.type == DialogueConstants.TYPE_RESPONSE else line.character + if notes_column > -1: + line_to_save[notes_column] = line.notes + + lines_to_save.append(line_to_save) + + # Store lines in the file, starting with anything that already exists that hasn't been touched + for line in existing_csv.values(): + file.store_csv_line(line) + for line in lines_to_save: + file.store_csv_line(line) + + file.close() + + editor_plugin.get_editor_interface().get_resource_filesystem().scan() + editor_plugin.get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", path) + + # Add it to the project l10n settings if it's not already there + var language_code: RegExMatch = RegEx.create_from_string("^[a-z]{2,3}").search(default_locale) + var translation_path: String = path.replace(".csv", ".%s.translation" % language_code.get_string()) + call_deferred("add_path_to_project_translations", translation_path) + + +func export_character_names_to_csv(path: String) -> void: + var file: FileAccess + + # If the file exists, open it first and work out which keys are already in it + var existing_csv = {} + var commas = [] + if FileAccess.file_exists(path): + file = FileAccess.open(path, FileAccess.READ) + var is_first_line = true + var line: Array + while !file.eof_reached(): + line = file.get_csv_line() + if is_first_line: + is_first_line = false + for i in range(2, line.size()): + commas.append("") + # Make sure the line isn't empty before adding it + if line.size() > 0 and line[0].strip_edges() != "": + existing_csv[line[0]] = line + + # Start a new file + file = FileAccess.open(path, FileAccess.WRITE) + + if not file.file_exists(path): + file.store_csv_line(["keys", DialogueSettings.get_setting("default_csv_locale", "en")]) + + # Write our translations to file + var known_keys: PackedStringArray = [] + + var character_names: PackedStringArray = DialogueManagerParser.parse_string(code_edit.text, current_file_path).character_names + + # Make a list of stuff that needs to go into the file + var lines_to_save = [] + for character_name in character_names: + if character_name in known_keys: continue + + known_keys.append(character_name) + + if existing_csv.has(character_name): + var existing_line = existing_csv.get(character_name) + existing_line[1] = character_name + lines_to_save.append(existing_line) + existing_csv.erase(character_name) + else: + lines_to_save.append(PackedStringArray([character_name, character_name] + commas)) + + # Store lines in the file, starting with anything that already exists that hasn't been touched + for line in existing_csv.values(): + file.store_csv_line(line) + for line in lines_to_save: + file.store_csv_line(line) + + file.close() + + editor_plugin.get_editor_interface().get_resource_filesystem().scan() + editor_plugin.get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", path) + + # Add it to the project l10n settings if it's not already there + var translation_path: String = path.replace(".csv", ".en.translation") + call_deferred("add_path_to_project_translations", translation_path) + + +# Import changes back from an exported CSV by matching translation keys +func import_translations_from_csv(path: String) -> void: + var cursor: Vector2 = code_edit.get_cursor() + + if not FileAccess.file_exists(path): return + + # Open the CSV file and build a dictionary of the known keys + var keys: Dictionary = {} + var file: FileAccess = FileAccess.open(path, FileAccess.READ) + var csv_line: Array + while !file.eof_reached(): + csv_line = file.get_csv_line() + if csv_line.size() > 1: + keys[csv_line[0]] = csv_line[1] + + var parser: DialogueManagerParser = DialogueManagerParser.new() + + # Now look over each line in the dialogue and replace the content for matched keys + var lines: PackedStringArray = code_edit.text.split("\n") + var start_index: int = 0 + var end_index: int = 0 + for i in range(0, lines.size()): + var line: String = lines[i] + var translation_key: String = parser.extract_translation(line) + if keys.has(translation_key): + if parser.is_dialogue_line(line): + start_index = 0 + # See if we need to skip over a character name + line = line.replace("\\:", "!ESCAPED_COLON!") + if ": " in line: + start_index = line.find(": ") + 2 + lines[i] = (line.substr(0, start_index) + keys.get(translation_key) + " [ID:" + translation_key + "]").replace("!ESCAPED_COLON!", ":") + + elif parser.is_response_line(line): + start_index = line.find("- ") + 2 + # See if we need to skip over a character name + line = line.replace("\\:", "!ESCAPED_COLON!") + if ": " in line: + start_index = line.find(": ") + 2 + end_index = line.length() + if " =>" in line: + end_index = line.find(" =>") + if " [if " in line: + end_index = line.find(" [if ") + lines[i] = (line.substr(0, start_index) + keys.get(translation_key) + " [ID:" + translation_key + "]" + line.substr(end_index)).replace("!ESCAPED_COLON!", ":") + + code_edit.text = "\n".join(lines) + code_edit.set_cursor(cursor) + + parser.free() + + +func show_search_form(is_enabled: bool) -> void: + if code_edit.last_selected_text: + search_and_replace.input.text = code_edit.last_selected_text + + search_and_replace.visible = is_enabled + search_button.set_pressed_no_signal(is_enabled) + search_and_replace.focus_line_edit() + + +### Signals + + +func _on_editor_settings_changed() -> void: + var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() + code_edit.minimap_draw = editor_settings.get_setting("text_editor/appearance/minimap/show_minimap") + code_edit.minimap_width = editor_settings.get_setting("text_editor/appearance/minimap/minimap_width") + code_edit.scroll_smooth = editor_settings.get_setting("text_editor/behavior/navigation/smooth_scrolling") + + +func _on_open_menu_id_pressed(id: int) -> void: + match id: + OPEN_OPEN: + open_dialog.popup_centered() + OPEN_CLEAR: + DialogueSettings.clear_recent_files() + build_open_menu() + _: + var menu = open_button.get_popup() + var item = menu.get_item_text(menu.get_item_index(id)) + open_file(item) + + +func _on_files_list_file_selected(file_path: String) -> void: + self.current_file_path = file_path + + +func _on_insert_button_menu_id_pressed(id: int) -> void: + match id: + 0: + code_edit.insert_bbcode("[wave amp=25 freq=5]", "[/wave]") + 1: + code_edit.insert_bbcode("[shake rate=20 level=10]", "[/shake]") + 3: + code_edit.insert_bbcode("[wait=1]") + 4: + code_edit.insert_bbcode("[speed=0.2]") + 5: + code_edit.insert_bbcode("[next=auto]") + 6: + code_edit.insert_text("~ title") + 7: + code_edit.insert_text("Nathan: This is Some Dialogue") + 8: + code_edit.insert_text("Nathan: Choose a Response...\n- Option 1\n\tNathan: You chose option 1\n- Option 2\n\tNathan: You chose option 2") + 9: + code_edit.insert_text("% Nathan: This is random line 1.\n% Nathan: This is random line 2.\n%1 Nathan: This is weighted random line 3.") + 10: + code_edit.insert_text("Nathan: [[Hi|Hello|Howdy]]") + 11: + code_edit.insert_text("=> title") + 12: + code_edit.insert_text("=> END") + + +func _on_translations_button_menu_id_pressed(id: int) -> void: + match id: + TRANSLATIONS_GENERATE_LINE_IDS: + generate_translations_keys() + + TRANSLATIONS_SAVE_CHARACTERS_TO_CSV: + translation_source = TranslationSource.CharacterNames + export_dialog.filters = PackedStringArray(["*.csv ; Translation CSV"]) + export_dialog.current_path = get_last_export_path("csv") + export_dialog.popup_centered() + + TRANSLATIONS_SAVE_TO_CSV: + translation_source = TranslationSource.Lines + export_dialog.filters = PackedStringArray(["*.csv ; Translation CSV"]) + export_dialog.current_path = get_last_export_path("csv") + export_dialog.popup_centered() + + TRANSLATIONS_IMPORT_FROM_CSV: + import_dialog.current_path = get_last_export_path("csv") + import_dialog.popup_centered() + + +func _on_export_dialog_file_selected(path: String) -> void: + DialogueSettings.set_user_value("last_export_path", path.get_base_dir()) + match path.get_extension(): + "csv": + match translation_source: + TranslationSource.CharacterNames: + export_character_names_to_csv(path) + TranslationSource.Lines: + export_translations_to_csv(path) + + +func _on_import_dialog_file_selected(path: String) -> void: + DialogueSettings.set_user_value("last_export_path", path.get_base_dir()) + import_translations_from_csv(path) + + +func _on_main_view_theme_changed(): + apply_theme() + + +func _on_main_view_visibility_changed() -> void: + if visible and is_instance_valid(code_edit): + code_edit.grab_focus() + + +func _on_new_button_pressed() -> void: + new_dialog.current_file = "" + new_dialog.popup_centered() + + +func _on_new_dialog_file_selected(path: String) -> void: + new_file(path) + open_file(path) + + +func _on_save_dialog_file_selected(path: String) -> void: + new_file(path, code_edit.text) + open_file(path) + + +func _on_open_button_about_to_popup() -> void: + build_open_menu() + + +func _on_open_dialog_file_selected(path: String) -> void: + open_file(path) + + +func _on_save_all_button_pressed() -> void: + save_files() + + +func _on_find_in_files_button_pressed() -> void: + find_in_files_dialog.popup_centered() + find_in_files.prepare() + + +func _on_code_edit_text_changed() -> void: + title_list.titles = code_edit.get_titles() + + var buffer = open_buffers[current_file_path] + buffer.text = code_edit.text + + files_list.mark_file_as_unsaved(current_file_path, buffer.text != buffer.pristine_text) + save_all_button.disabled = open_buffers.values().filter(func(d): return d.text != d.pristine_text).size() == 0 + + parse_timer.start(1) + + +func _on_code_edit_active_title_change(title: String) -> void: + title_list.select_title(title) + DialogueSettings.set_user_value("run_title", title) + + +func _on_code_edit_caret_changed() -> void: + DialogueSettings.set_caret(current_file_path, code_edit.get_cursor()) + + +func _on_code_edit_error_clicked(line_number: int) -> void: + errors_panel.show_error_for_line_number(line_number) + + +func _on_title_list_title_selected(title: String) -> void: + code_edit.go_to_title(title) + code_edit.grab_focus() + + +func _on_parse_timer_timeout() -> void: + parse_timer.stop() + parse() + + +func _on_errors_panel_error_pressed(line_number: int, column_number: int) -> void: + code_edit.set_caret_line(line_number) + code_edit.set_caret_column(column_number) + code_edit.grab_focus() + + +func _on_search_button_toggled(button_pressed: bool) -> void: + show_search_form(button_pressed) + + +func _on_search_and_replace_open_requested() -> void: + show_search_form(true) + + +func _on_search_and_replace_close_requested() -> void: + search_button.set_pressed_no_signal(false) + search_and_replace.visible = false + code_edit.grab_focus() + + +func _on_settings_button_pressed() -> void: + settings_view.prepare() + settings_dialog.popup_centered() + + +func _on_settings_view_script_button_pressed(path: String) -> void: + settings_dialog.hide() + editor_plugin.get_editor_interface().edit_resource(load(path)) + + +func _on_test_button_pressed() -> void: + save_file(current_file_path) + + if errors_panel.errors.size() > 0: + errors_dialog.popup_centered() + return + + DialogueSettings.set_user_value("is_running_test_scene", true) + DialogueSettings.set_user_value("run_resource_path", current_file_path) + var test_scene_path: String = DialogueSettings.get_setting("custom_test_scene_path", "res://addons/dialogue_manager/test_scene.tscn") + editor_plugin.get_editor_interface().play_custom_scene(test_scene_path) + + +func _on_settings_dialog_confirmed() -> void: + settings_view.apply_settings_changes() + parse() + code_edit.wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY if DialogueSettings.get_setting("wrap_lines", false) else TextEdit.LINE_WRAPPING_NONE + code_edit.grab_focus() + + +func _on_support_button_pressed() -> void: + OS.shell_open("https://patreon.com/nathanhoad") + + +func _on_docs_button_pressed() -> void: + OS.shell_open("https://github.com/nathanhoad/godot_dialogue_manager") + + +func _on_files_list_file_popup_menu_requested(at_position: Vector2) -> void: + files_popup_menu.position = Vector2(get_viewport().position) + files_list.global_position + at_position + files_popup_menu.popup() + + +func _on_files_list_file_middle_clicked(path: String): + close_file(path) + + +func _on_files_popup_menu_about_to_popup() -> void: + files_popup_menu.clear() + + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save"), ITEM_SAVE, KEY_MASK_CTRL | KEY_MASK_ALT | KEY_S) + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save_as"), ITEM_SAVE_AS) + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close"), ITEM_CLOSE, KEY_MASK_CTRL | KEY_W) + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_all"), ITEM_CLOSE_ALL) + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_other_files"), ITEM_CLOSE_OTHERS) + files_popup_menu.add_separator() + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.copy_file_path"), ITEM_COPY_PATH) + files_popup_menu.add_item(DialogueConstants.translate(&"buffer.show_in_filesystem"), ITEM_SHOW_IN_FILESYSTEM) + + +func _on_files_popup_menu_id_pressed(id: int) -> void: + match id: + ITEM_SAVE: + save_file(current_file_path) + ITEM_SAVE_AS: + save_dialog.popup_centered() + ITEM_CLOSE: + close_file(current_file_path) + ITEM_CLOSE_ALL: + for path in open_buffers.keys(): + close_file(path) + ITEM_CLOSE_OTHERS: + for path in open_buffers.keys(): + if path != current_file_path: + close_file(path) + + ITEM_COPY_PATH: + DisplayServer.clipboard_set(current_file_path) + ITEM_SHOW_IN_FILESYSTEM: + show_file_in_filesystem(current_file_path) + + +func _on_code_edit_external_file_requested(path: String, title: String) -> void: + open_file(path) + if title != "": + code_edit.go_to_title(title) + else: + code_edit.set_caret_line(0) + + +func _on_close_confirmation_dialog_confirmed() -> void: + save_file(current_file_path) + remove_file_from_open_buffers(current_file_path) + + +func _on_close_confirmation_dialog_custom_action(action: StringName) -> void: + if action == "discard": + remove_file_from_open_buffers(current_file_path) + close_confirmation_dialog.hide() + + +func _on_find_in_files_result_selected(path: String, cursor: Vector2, length: int) -> void: + open_file(path) + code_edit.select(cursor.y, cursor.x, cursor.y, cursor.x + length) diff --git a/addons/dialogue_manager/views/main_view.tscn b/addons/dialogue_manager/views/main_view.tscn new file mode 100644 index 0000000..d57bdf9 --- /dev/null +++ b/addons/dialogue_manager/views/main_view.tscn @@ -0,0 +1,334 @@ +[gd_scene load_steps=14 format=3 uid="uid://cbuf1q3xsse3q"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/views/main_view.gd" id="1_h6qfq"] +[ext_resource type="PackedScene" uid="uid://civ6shmka5e8u" path="res://addons/dialogue_manager/components/code_edit.tscn" id="2_f73fm"] +[ext_resource type="PackedScene" uid="uid://dnufpcdrreva3" path="res://addons/dialogue_manager/components/files_list.tscn" id="2_npj2k"] +[ext_resource type="PackedScene" uid="uid://ctns6ouwwd68i" path="res://addons/dialogue_manager/components/title_list.tscn" id="2_onb4i"] +[ext_resource type="PackedScene" uid="uid://co8yl23idiwbi" path="res://addons/dialogue_manager/components/update_button.tscn" id="2_ph3vs"] +[ext_resource type="PackedScene" uid="uid://gr8nakpbrhby" path="res://addons/dialogue_manager/components/search_and_replace.tscn" id="6_ylh0t"] +[ext_resource type="PackedScene" uid="uid://cs8pwrxr5vxix" path="res://addons/dialogue_manager/components/errors_panel.tscn" id="7_5cvl4"] +[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit_syntax_highlighter.gd" id="7_necsa"] +[ext_resource type="PackedScene" uid="uid://cpg4lg1r3ff6m" path="res://addons/dialogue_manager/views/settings_view.tscn" id="9_8bf36"] +[ext_resource type="PackedScene" uid="uid://0n7hwviyyly4" path="res://addons/dialogue_manager/components/find_in_files.tscn" id="10_yold3"] + +[sub_resource type="Image" id="Image_xvtti"] +data = { +"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), +"format": "RGBA8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id="ImageTexture_fguub"] +image = SubResource("Image_xvtti") + +[sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_dvnxt"] +script = ExtResource("7_necsa") + +[node name="MainView" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("1_h6qfq") + +[node name="ParseTimer" type="Timer" parent="."] + +[node name="Margin" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_vertical = 3 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_bottom = 5 +metadata/_edit_layout_mode = 1 + +[node name="Content" type="HSplitContainer" parent="Margin"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +dragger_visibility = 1 + +[node name="SidePanel" type="VBoxContainer" parent="Margin/Content"] +custom_minimum_size = Vector2(150, 0) +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Toolbar" type="HBoxContainer" parent="Margin/Content/SidePanel"] +layout_mode = 2 + +[node name="NewButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Start a new file" +flat = true + +[node name="OpenButton" type="MenuButton" parent="Margin/Content/SidePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Open a file" + +[node name="SaveAllButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +disabled = true +flat = true + +[node name="FindInFilesButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +flat = true + +[node name="Bookmarks" type="VSplitContainer" parent="Margin/Content/SidePanel"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="FilesList" parent="Margin/Content/SidePanel/Bookmarks" instance=ExtResource("2_npj2k")] +unique_name_in_owner = true +visible = false +layout_mode = 2 +size_flags_vertical = 3 + +[node name="FilesPopupMenu" type="PopupMenu" parent="Margin/Content/SidePanel/Bookmarks/FilesList"] +unique_name_in_owner = true + +[node name="TitleList" parent="Margin/Content/SidePanel/Bookmarks" instance=ExtResource("2_onb4i")] +unique_name_in_owner = true +visible = false +layout_mode = 2 + +[node name="CodePanel" type="VBoxContainer" parent="Margin/Content"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 4.0 + +[node name="Toolbar" type="HBoxContainer" parent="Margin/Content/CodePanel"] +layout_mode = 2 + +[node name="InsertButton" type="MenuButton" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +disabled = true +text = "Insert" + +[node name="TranslationsButton" type="MenuButton" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +disabled = true +text = "Translations" +item_count = 6 +popup/item_0/text = "Generate line IDs" +popup/item_0/icon = SubResource("ImageTexture_fguub") +popup/item_0/id = 0 +popup/item_1/text = "" +popup/item_1/id = -1 +popup/item_1/separator = true +popup/item_2/text = "Save to CSV..." +popup/item_2/icon = SubResource("ImageTexture_fguub") +popup/item_2/id = 2 +popup/item_3/text = "Import changes from CSV..." +popup/item_3/icon = SubResource("ImageTexture_fguub") +popup/item_3/id = 3 +popup/item_4/text = "" +popup/item_4/id = -1 +popup/item_4/separator = true +popup/item_5/text = "Save to PO..." +popup/item_5/icon = SubResource("ImageTexture_fguub") +popup/item_5/id = 5 + +[node name="Separator" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] +layout_mode = 2 + +[node name="SearchButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Search for text" +disabled = true +toggle_mode = true +flat = true + +[node name="TestButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Test dialogue" +disabled = true +flat = true + +[node name="Separator3" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] +layout_mode = 2 + +[node name="SettingsButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Settings" +flat = true + +[node name="Spacer2" type="Control" parent="Margin/Content/CodePanel/Toolbar"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="SupportButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +flat = true + +[node name="Separator4" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] +layout_mode = 2 + +[node name="DocsButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +layout_mode = 2 +text = "Docs" +flat = true + +[node name="VersionLabel" type="Label" parent="Margin/Content/CodePanel/Toolbar"] +unique_name_in_owner = true +modulate = Color(1, 1, 1, 0.490196) +layout_mode = 2 +text = "v2.19.0" +vertical_alignment = 1 + +[node name="UpdateButton" parent="Margin/Content/CodePanel/Toolbar" instance=ExtResource("2_ph3vs")] +unique_name_in_owner = true +layout_mode = 2 + +[node name="SearchAndReplace" parent="Margin/Content/CodePanel" instance=ExtResource("6_ylh0t")] +unique_name_in_owner = true +layout_mode = 2 + +[node name="CodeEdit" parent="Margin/Content/CodePanel" instance=ExtResource("2_f73fm")] +unique_name_in_owner = true +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_colors/bookmark_color = Color(1, 0.333333, 0.333333, 1) +text = "" +syntax_highlighter = SubResource("SyntaxHighlighter_dvnxt") + +[node name="ErrorsPanel" parent="Margin/Content/CodePanel" instance=ExtResource("7_5cvl4")] +unique_name_in_owner = true +layout_mode = 2 + +[node name="NewDialog" type="FileDialog" parent="."] +size = Vector2i(600, 500) +min_size = Vector2i(600, 500) +dialog_hide_on_ok = true +filters = PackedStringArray("*.dialogue ; Dialogue") + +[node name="SaveDialog" type="FileDialog" parent="."] +size = Vector2i(600, 500) +min_size = Vector2i(600, 500) +dialog_hide_on_ok = true +filters = PackedStringArray("*.dialogue ; Dialogue") + +[node name="OpenDialog" type="FileDialog" parent="."] +title = "Open a File" +size = Vector2i(600, 500) +min_size = Vector2i(600, 500) +ok_button_text = "Open" +dialog_hide_on_ok = true +file_mode = 0 +filters = PackedStringArray("*.dialogue ; Dialogue") + +[node name="ExportDialog" type="FileDialog" parent="."] +size = Vector2i(600, 500) +min_size = Vector2i(600, 500) + +[node name="ImportDialog" type="FileDialog" parent="."] +title = "Open a File" +size = Vector2i(600, 500) +min_size = Vector2i(600, 500) +ok_button_text = "Open" +file_mode = 0 +filters = PackedStringArray("*.csv ; Translation CSV") + +[node name="ErrorsDialog" type="AcceptDialog" parent="."] +title = "Error" +dialog_text = "You have errors in your script. Fix them and then try again." + +[node name="SettingsDialog" type="AcceptDialog" parent="."] +title = "Settings" +size = Vector2i(834, 600) +unresizable = true +min_size = Vector2i(600, 600) +ok_button_text = "Done" + +[node name="SettingsView" parent="SettingsDialog" instance=ExtResource("9_8bf36")] +offset_left = 8.0 +offset_top = 8.0 +offset_right = -8.0 +offset_bottom = -49.0 + +[node name="BuildErrorDialog" type="AcceptDialog" parent="."] +title = "Errors" +dialog_text = "You need to fix dialogue errors before you can run your game." + +[node name="CloseConfirmationDialog" type="ConfirmationDialog" parent="."] +title = "Unsaved changes" +ok_button_text = "Save changes" + +[node name="UpdatedDialog" type="AcceptDialog" parent="."] +title = "Updated" +size = Vector2i(191, 100) +dialog_text = "You're now up to date!" + +[node name="FindInFilesDialog" type="AcceptDialog" parent="."] +title = "Find in files" +size = Vector2i(416, 457) +ok_button_text = "Done" + +[node name="FindInFiles" parent="FindInFilesDialog" node_paths=PackedStringArray("main_view", "code_edit") instance=ExtResource("10_yold3")] +custom_minimum_size = Vector2(400, 400) +offset_left = 8.0 +offset_top = 8.0 +offset_right = -8.0 +offset_bottom = -49.0 +main_view = NodePath("../..") +code_edit = NodePath("../../Margin/Content/CodePanel/CodeEdit") + +[connection signal="theme_changed" from="." to="." method="_on_main_view_theme_changed"] +[connection signal="visibility_changed" from="." to="." method="_on_main_view_visibility_changed"] +[connection signal="timeout" from="ParseTimer" to="." method="_on_parse_timer_timeout"] +[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/NewButton" to="." method="_on_new_button_pressed"] +[connection signal="about_to_popup" from="Margin/Content/SidePanel/Toolbar/OpenButton" to="." method="_on_open_button_about_to_popup"] +[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/SaveAllButton" to="." method="_on_save_all_button_pressed"] +[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/FindInFilesButton" to="." method="_on_find_in_files_button_pressed"] +[connection signal="file_middle_clicked" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_middle_clicked"] +[connection signal="file_popup_menu_requested" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_popup_menu_requested"] +[connection signal="file_selected" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_selected"] +[connection signal="about_to_popup" from="Margin/Content/SidePanel/Bookmarks/FilesList/FilesPopupMenu" to="." method="_on_files_popup_menu_about_to_popup"] +[connection signal="id_pressed" from="Margin/Content/SidePanel/Bookmarks/FilesList/FilesPopupMenu" to="." method="_on_files_popup_menu_id_pressed"] +[connection signal="title_selected" from="Margin/Content/SidePanel/Bookmarks/TitleList" to="." method="_on_title_list_title_selected"] +[connection signal="toggled" from="Margin/Content/CodePanel/Toolbar/SearchButton" to="." method="_on_search_button_toggled"] +[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/TestButton" to="." method="_on_test_button_pressed"] +[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/SettingsButton" to="." method="_on_settings_button_pressed"] +[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/SupportButton" to="." method="_on_support_button_pressed"] +[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/DocsButton" to="." method="_on_docs_button_pressed"] +[connection signal="close_requested" from="Margin/Content/CodePanel/SearchAndReplace" to="." method="_on_search_and_replace_close_requested"] +[connection signal="open_requested" from="Margin/Content/CodePanel/SearchAndReplace" to="." method="_on_search_and_replace_open_requested"] +[connection signal="active_title_change" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_active_title_change"] +[connection signal="caret_changed" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_caret_changed"] +[connection signal="error_clicked" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_error_clicked"] +[connection signal="external_file_requested" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_external_file_requested"] +[connection signal="text_changed" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_text_changed"] +[connection signal="error_pressed" from="Margin/Content/CodePanel/ErrorsPanel" to="." method="_on_errors_panel_error_pressed"] +[connection signal="file_selected" from="NewDialog" to="." method="_on_new_dialog_file_selected"] +[connection signal="file_selected" from="SaveDialog" to="." method="_on_save_dialog_file_selected"] +[connection signal="file_selected" from="OpenDialog" to="." method="_on_open_dialog_file_selected"] +[connection signal="file_selected" from="ExportDialog" to="." method="_on_export_dialog_file_selected"] +[connection signal="file_selected" from="ImportDialog" to="." method="_on_import_dialog_file_selected"] +[connection signal="confirmed" from="SettingsDialog" to="." method="_on_settings_dialog_confirmed"] +[connection signal="script_button_pressed" from="SettingsDialog/SettingsView" to="." method="_on_settings_view_script_button_pressed"] +[connection signal="confirmed" from="CloseConfirmationDialog" to="." method="_on_close_confirmation_dialog_confirmed"] +[connection signal="custom_action" from="CloseConfirmationDialog" to="." method="_on_close_confirmation_dialog_custom_action"] +[connection signal="result_selected" from="FindInFilesDialog/FindInFiles" to="." method="_on_find_in_files_result_selected"] diff --git a/addons/dialogue_manager/views/settings_view.gd b/addons/dialogue_manager/views/settings_view.gd new file mode 100644 index 0000000..8ab4e95 --- /dev/null +++ b/addons/dialogue_manager/views/settings_view.gd @@ -0,0 +1,280 @@ +@tool +extends TabContainer + + +signal script_button_pressed(path: String) + + +const DialogueConstants = preload("../constants.gd") +const DialogueSettings = preload("../settings.gd") + + +enum PathTarget { + CustomTestScene, + Balloon +} + + +# Editor +@onready var new_template_button: CheckBox = $Editor/NewTemplateButton +@onready var characters_translations_button: CheckBox = $Editor/CharactersTranslationsButton +@onready var wrap_lines_button: Button = $Editor/WrapLinesButton +@onready var default_csv_locale: LineEdit = $Editor/DefaultCSVLocale + +# Runtime +@onready var include_all_responses_button: CheckBox = $Runtime/IncludeAllResponsesButton +@onready var ignore_missing_state_values: CheckBox = $Runtime/IgnoreMissingStateValues +@onready var balloon_path_input: LineEdit = $Runtime/CustomBalloon/BalloonPath +@onready var revert_balloon_button: Button = $Runtime/CustomBalloon/RevertBalloonPath +@onready var load_balloon_button: Button = $Runtime/CustomBalloon/LoadBalloonPath +@onready var states_title: Label = $Runtime/StatesTitle +@onready var globals_list: Tree = $Runtime/GlobalsList + +# Advanced +@onready var check_for_updates: CheckBox = $Advanced/CheckForUpdates +@onready var include_characters_in_translations: CheckBox = $Advanced/IncludeCharactersInTranslations +@onready var include_notes_in_translations: CheckBox = $Advanced/IncludeNotesInTranslations +@onready var open_in_external_editor_button: CheckBox = $Advanced/OpenInExternalEditorButton +@onready var test_scene_path_input: LineEdit = $Advanced/CustomTestScene/TestScenePath +@onready var revert_test_scene_button: Button = $Advanced/CustomTestScene/RevertTestScene +@onready var load_test_scene_button: Button = $Advanced/CustomTestScene/LoadTestScene +@onready var custom_test_scene_file_dialog: FileDialog = $CustomTestSceneFileDialog +@onready var create_lines_for_response_characters: CheckBox = $Advanced/CreateLinesForResponseCharacters +@onready var missing_translations_button: CheckBox = $Advanced/MissingTranslationsButton + +var editor_plugin: EditorPlugin +var all_globals: Dictionary = {} +var enabled_globals: Array = [] +var path_target: PathTarget = PathTarget.CustomTestScene + +var _default_test_scene_path: String = preload("../test_scene.tscn").resource_path + +var _recompile_if_changed_settings: Dictionary + + +func _ready() -> void: + new_template_button.text = DialogueConstants.translate(&"settings.new_template") + $Editor/MissingTranslationsHint.text = DialogueConstants.translate(&"settings.missing_keys_hint") + characters_translations_button.text = DialogueConstants.translate(&"settings.characters_translations") + wrap_lines_button.text = DialogueConstants.translate(&"settings.wrap_long_lines") + $Editor/DefaultCSVLocaleLabel.text = DialogueConstants.translate(&"settings.default_csv_locale") + + include_all_responses_button.text = DialogueConstants.translate(&"settings.include_failed_responses") + ignore_missing_state_values.text = DialogueConstants.translate(&"settings.ignore_missing_state_values") + $Runtime/CustomBalloonLabel.text = DialogueConstants.translate(&"settings.default_balloon_hint") + states_title.text = DialogueConstants.translate(&"settings.states_shortcuts") + $Runtime/StatesMessage.text = DialogueConstants.translate(&"settings.states_message") + $Runtime/StatesHint.text = DialogueConstants.translate(&"settings.states_hint") + + check_for_updates.text = DialogueConstants.translate(&"settings.check_for_updates") + include_characters_in_translations.text = DialogueConstants.translate(&"settings.include_characters_in_translations") + include_notes_in_translations.text = DialogueConstants.translate(&"settings.include_notes_in_translations") + open_in_external_editor_button.text = DialogueConstants.translate(&"settings.open_in_external_editor") + $Advanced/ExternalWarning.text = DialogueConstants.translate(&"settings.external_editor_warning") + $Advanced/CustomTestSceneLabel.text = DialogueConstants.translate(&"settings.custom_test_scene") + $Advanced/RecompileWarning.text = DialogueConstants.translate(&"settings.recompile_warning") + missing_translations_button.text = DialogueConstants.translate(&"settings.missing_keys") + create_lines_for_response_characters.text = DialogueConstants.translate(&"settings.create_lines_for_responses_with_characters") + + current_tab = 0 + + +func prepare() -> void: + _recompile_if_changed_settings = _get_settings_that_require_recompilation() + + test_scene_path_input.placeholder_text = DialogueSettings.get_setting("custom_test_scene_path", _default_test_scene_path) + revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path + revert_test_scene_button.icon = get_theme_icon("RotateLeft", "EditorIcons") + revert_test_scene_button.tooltip_text = DialogueConstants.translate(&"settings.revert_to_default_test_scene") + load_test_scene_button.icon = get_theme_icon("Load", "EditorIcons") + + var balloon_path: String = DialogueSettings.get_setting("balloon_path", "") + if not FileAccess.file_exists(balloon_path): + DialogueSettings.set_setting("balloon_path", "") + balloon_path = "" + balloon_path_input.placeholder_text = balloon_path if balloon_path != "" else DialogueConstants.translate(&"settings.default_balloon_path") + revert_balloon_button.visible = balloon_path != "" + revert_balloon_button.icon = get_theme_icon("RotateLeft", "EditorIcons") + revert_balloon_button.tooltip_text = DialogueConstants.translate(&"settings.revert_to_default_balloon") + load_balloon_button.icon = get_theme_icon("Load", "EditorIcons") + + var scale: float = editor_plugin.get_editor_interface().get_editor_scale() + custom_test_scene_file_dialog.min_size = Vector2(600, 500) * scale + + states_title.add_theme_font_override("font", get_theme_font("bold", "EditorFonts")) + + check_for_updates.set_pressed_no_signal(DialogueSettings.get_user_value("check_for_updates", true)) + characters_translations_button.set_pressed_no_signal(DialogueSettings.get_setting("export_characters_in_translation", true)) + wrap_lines_button.set_pressed_no_signal(DialogueSettings.get_setting("wrap_lines", false)) + include_all_responses_button.set_pressed_no_signal(DialogueSettings.get_setting("include_all_responses", false)) + ignore_missing_state_values.set_pressed_no_signal(DialogueSettings.get_setting("ignore_missing_state_values", false)) + new_template_button.set_pressed_no_signal(DialogueSettings.get_setting("new_with_template", true)) + default_csv_locale.text = DialogueSettings.get_setting("default_csv_locale", "en") + + missing_translations_button.set_pressed_no_signal(DialogueSettings.get_setting("missing_translations_are_errors", false)) + create_lines_for_response_characters.set_pressed_no_signal(DialogueSettings.get_setting("create_lines_for_responses_with_characters", true)) + + include_characters_in_translations.set_pressed_no_signal(DialogueSettings.get_setting("include_character_in_translation_exports", false)) + include_notes_in_translations.set_pressed_no_signal(DialogueSettings.get_setting("include_notes_in_translation_exports", false)) + open_in_external_editor_button.set_pressed_no_signal(DialogueSettings.get_user_value("open_in_external_editor", false)) + + var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() + var external_editor: String = editor_settings.get_setting("text_editor/external/exec_path") + var use_external_editor: bool = editor_settings.get_setting("text_editor/external/use_external_editor") and external_editor != "" + if not use_external_editor: + open_in_external_editor_button.hide() + $Advanced/ExternalWarning.hide() + $Advanced/ExternalSeparator.hide() + + var project = ConfigFile.new() + var err = project.load("res://project.godot") + assert(err == OK, "Could not find the project file") + + all_globals.clear() + if project.has_section("autoload"): + for key in project.get_section_keys("autoload"): + if key != "DialogueManager": + all_globals[key] = project.get_value("autoload", key) + + enabled_globals = DialogueSettings.get_setting("states", []).duplicate() + globals_list.clear() + var root = globals_list.create_item() + for name in all_globals.keys(): + var item: TreeItem = globals_list.create_item(root) + item.set_cell_mode(0, TreeItem.CELL_MODE_CHECK) + item.set_checked(0, name in enabled_globals) + item.set_text(0, name) + item.add_button(1, get_theme_icon("Edit", "EditorIcons")) + item.set_text(2, all_globals.get(name, "").replace("*res://", "res://")) + + globals_list.set_column_expand(0, false) + globals_list.set_column_custom_minimum_width(0, 250) + globals_list.set_column_expand(1, false) + globals_list.set_column_custom_minimum_width(1, 40) + globals_list.set_column_titles_visible(true) + globals_list.set_column_title(0, DialogueConstants.translate(&"settings.autoload")) + globals_list.set_column_title(1, "") + globals_list.set_column_title(2, DialogueConstants.translate(&"settings.path")) + + +func apply_settings_changes() -> void: + if _recompile_if_changed_settings != _get_settings_that_require_recompilation(): + Engine.get_meta("DialogueCache").reimport_files() + + +func _get_settings_that_require_recompilation() -> Dictionary: + return DialogueSettings.get_settings([ + "missing_translations_are_errors", + "create_lines_for_responses_with_characters" + ]) + + +### Signals + + +func _on_missing_translations_button_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("missing_translations_are_errors", toggled_on) + + +func _on_characters_translations_button_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("export_characters_in_translation", toggled_on) + + +func _on_wrap_lines_button_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("wrap_lines", toggled_on) + + +func _on_include_all_responses_button_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("include_all_responses", toggled_on) + + +func _on_globals_list_item_selected() -> void: + var item = globals_list.get_selected() + var is_checked = not item.is_checked(0) + item.set_checked(0, is_checked) + + if is_checked: + enabled_globals.append(item.get_text(0)) + else: + enabled_globals.erase(item.get_text(0)) + + DialogueSettings.set_setting("states", enabled_globals) + + +func _on_globals_list_button_clicked(item: TreeItem, column: int, id: int, mouse_button_index: int) -> void: + emit_signal("script_button_pressed", item.get_text(2)) + + +func _on_sample_template_toggled(toggled_on): + DialogueSettings.set_setting("new_with_template", toggled_on) + + +func _on_revert_test_scene_pressed() -> void: + DialogueSettings.set_setting("custom_test_scene_path", _default_test_scene_path) + test_scene_path_input.placeholder_text = _default_test_scene_path + revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path + + +func _on_load_test_scene_pressed() -> void: + path_target = PathTarget.CustomTestScene + custom_test_scene_file_dialog.popup_centered() + + +func _on_custom_test_scene_file_dialog_file_selected(path: String) -> void: + match path_target: + PathTarget.CustomTestScene: + # Check that the test scene is a subclass of BaseDialogueTestScene + var test_scene: PackedScene = load(path) + if test_scene and test_scene.instantiate() is BaseDialogueTestScene: + DialogueSettings.set_setting("custom_test_scene_path", path) + test_scene_path_input.placeholder_text = path + revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path + else: + var accept: AcceptDialog = AcceptDialog.new() + accept.dialog_text = DialogueConstants.translate(&"settings.invalid_test_scene").format({ path = path }) + add_child(accept) + accept.popup_centered.call_deferred() + + PathTarget.Balloon: + DialogueSettings.set_setting("balloon_path", path) + balloon_path_input.placeholder_text = path + revert_balloon_button.visible = balloon_path_input.placeholder_text != "" + + +func _on_ignore_missing_state_values_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("ignore_missing_state_values", toggled_on) + + +func _on_default_csv_locale_text_changed(new_text: String) -> void: + DialogueSettings.set_setting("default_csv_locale", new_text) + + +func _on_revert_balloon_path_pressed() -> void: + DialogueSettings.set_setting("balloon_path", "") + balloon_path_input.placeholder_text = DialogueConstants.translate(&"settings.default_balloon_path") + revert_balloon_button.visible = DialogueSettings.get_setting("balloon_path", "") != "" + + +func _on_load_balloon_path_pressed() -> void: + path_target = PathTarget.Balloon + custom_test_scene_file_dialog.popup_centered() + + +func _on_create_lines_for_response_characters_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("create_lines_for_responses_with_characters", toggled_on) + + +func _on_open_in_external_editor_button_toggled(toggled_on: bool) -> void: + DialogueSettings.set_user_value("open_in_external_editor", toggled_on) + + +func _on_include_characters_in_translations_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("include_character_in_translation_exports", toggled_on) + + +func _on_include_notes_in_translations_toggled(toggled_on: bool) -> void: + DialogueSettings.set_setting("include_notes_in_translation_exports", toggled_on) + + +func _on_keep_up_to_date_toggled(toggled_on: bool) -> void: + DialogueSettings.set_user_value("check_for_updates", toggled_on) diff --git a/addons/dialogue_manager/views/settings_view.tscn b/addons/dialogue_manager/views/settings_view.tscn new file mode 100644 index 0000000..09df0a2 --- /dev/null +++ b/addons/dialogue_manager/views/settings_view.tscn @@ -0,0 +1,221 @@ +[gd_scene load_steps=3 format=3 uid="uid://cpg4lg1r3ff6m"] + +[ext_resource type="Script" path="res://addons/dialogue_manager/views/settings_view.gd" id="1_06uxa"] + +[sub_resource type="Theme" id="Theme_3a8rc"] +HSeparator/constants/separation = 20 + +[node name="SettingsView" type="TabContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = -206.0 +offset_bottom = -345.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme = SubResource("Theme_3a8rc") +current_tab = 2 +script = ExtResource("1_06uxa") + +[node name="Editor" type="VBoxContainer" parent="."] +visible = false +layout_mode = 2 + +[node name="NewTemplateButton" type="CheckBox" parent="Editor"] +layout_mode = 2 +button_pressed = true +text = "New dialogue files will start with template text" + +[node name="MissingTranslationsHint" type="Label" parent="Editor"] +modulate = Color(1, 1, 1, 0.501961) +custom_minimum_size = Vector2(10, 0) +layout_mode = 2 +text = "If you are using static translation keys then having this enabled will help you find any lines that you haven't added a key to yet." +autowrap_mode = 3 + +[node name="CharactersTranslationsButton" type="CheckBox" parent="Editor"] +layout_mode = 2 +button_pressed = true +text = "Export character names in translation files" + +[node name="WrapLinesButton" type="CheckBox" parent="Editor"] +layout_mode = 2 +button_pressed = true +text = "Wrap long lines" + +[node name="HSeparator" type="HSeparator" parent="Editor"] +layout_mode = 2 + +[node name="DefaultCSVLocaleLabel" type="Label" parent="Editor"] +layout_mode = 2 +text = "Default CSV Locale" + +[node name="DefaultCSVLocale" type="LineEdit" parent="Editor"] +layout_mode = 2 + +[node name="Runtime" type="VBoxContainer" parent="."] +visible = false +layout_mode = 2 + +[node name="IncludeAllResponsesButton" type="CheckBox" parent="Runtime"] +layout_mode = 2 +text = "Include responses with failed conditions" + +[node name="IgnoreMissingStateValues" type="CheckBox" parent="Runtime"] +layout_mode = 2 +text = "Skip over missing state value errors (not recommended)" + +[node name="HSeparator" type="HSeparator" parent="Runtime"] +layout_mode = 2 + +[node name="CustomBalloonLabel" type="Label" parent="Runtime"] +layout_mode = 2 +text = "Custom balloon to use when calling \"DialogueManager.show_balloon()\"" + +[node name="CustomBalloon" type="HBoxContainer" parent="Runtime"] +layout_mode = 2 + +[node name="BalloonPath" type="LineEdit" parent="Runtime/CustomBalloon"] +layout_mode = 2 +size_flags_horizontal = 3 +focus_mode = 0 +editable = false +shortcut_keys_enabled = false +middle_mouse_paste_enabled = false + +[node name="RevertBalloonPath" type="Button" parent="Runtime/CustomBalloon"] +visible = false +layout_mode = 2 +tooltip_text = "Revert to default test scene" +flat = true + +[node name="LoadBalloonPath" type="Button" parent="Runtime/CustomBalloon"] +layout_mode = 2 + +[node name="HSeparator2" type="HSeparator" parent="Runtime"] +layout_mode = 2 + +[node name="StatesTitle" type="Label" parent="Runtime"] +layout_mode = 2 +text = "State Shortcuts" + +[node name="StatesMessage" type="Label" parent="Runtime"] +layout_mode = 2 +text = "If an autoload is enabled here you can refer to its properties and methods without having to use its name." + +[node name="StatesHint" type="Label" parent="Runtime"] +modulate = Color(1, 1, 1, 0.501961) +custom_minimum_size = Vector2(10, 0) +layout_mode = 2 +text = "ie. Instead of \"SomeState.some_property\" you could just use \"some_property\"" +autowrap_mode = 3 + +[node name="GlobalsList" type="Tree" parent="Runtime"] +layout_mode = 2 +size_flags_vertical = 3 +columns = 3 +column_titles_visible = true +allow_reselect = true +hide_folding = true +hide_root = true +select_mode = 1 + +[node name="Advanced" type="VBoxContainer" parent="."] +layout_mode = 2 + +[node name="CheckForUpdates" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Check for updates" + +[node name="HSeparator" type="HSeparator" parent="Advanced"] +layout_mode = 2 + +[node name="IncludeCharactersInTranslations" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Include character names in translation exports" + +[node name="IncludeNotesInTranslations" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Include notes (## comments) in translation exports" + +[node name="ExternalSeparator" type="HSeparator" parent="Advanced"] +layout_mode = 2 + +[node name="OpenInExternalEditorButton" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Open dialogue files in external editor" + +[node name="ExternalWarning" type="Label" parent="Advanced"] +layout_mode = 2 +text = "Note: Syntax highlighting and detailed error checking are not supported in external editors." + +[node name="HSeparator3" type="HSeparator" parent="Advanced"] +layout_mode = 2 + +[node name="CustomTestSceneLabel" type="Label" parent="Advanced"] +layout_mode = 2 +text = "Custom test scene (must extend BaseDialogueTestScene)" + +[node name="CustomTestScene" type="HBoxContainer" parent="Advanced"] +layout_mode = 2 + +[node name="TestScenePath" type="LineEdit" parent="Advanced/CustomTestScene"] +layout_mode = 2 +size_flags_horizontal = 3 +focus_mode = 0 +placeholder_text = "res://addons/dialogue_manager/test_scene.tscn" +editable = false +shortcut_keys_enabled = false +middle_mouse_paste_enabled = false + +[node name="RevertTestScene" type="Button" parent="Advanced/CustomTestScene"] +visible = false +layout_mode = 2 +tooltip_text = "Revert to default test scene" +flat = true + +[node name="LoadTestScene" type="Button" parent="Advanced/CustomTestScene"] +layout_mode = 2 + +[node name="HSeparator4" type="HSeparator" parent="Advanced"] +layout_mode = 2 + +[node name="RecompileWarning" type="Label" parent="Advanced"] +layout_mode = 2 +text = "Changing these settings will force a recompile of all dialogue. Only change them if you know what you are doing." + +[node name="MissingTranslationsButton" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Treat missing translation keys as errors" + +[node name="CreateLinesForResponseCharacters" type="CheckBox" parent="Advanced"] +layout_mode = 2 +text = "Create child dialogue line for responses with character names in them" + +[node name="CustomTestSceneFileDialog" type="FileDialog" parent="."] +title = "Open a File" +ok_button_text = "Open" +file_mode = 0 +filters = PackedStringArray("*.tscn ; Scene") + +[connection signal="toggled" from="Editor/NewTemplateButton" to="." method="_on_sample_template_toggled"] +[connection signal="toggled" from="Editor/CharactersTranslationsButton" to="." method="_on_characters_translations_button_toggled"] +[connection signal="toggled" from="Editor/WrapLinesButton" to="." method="_on_wrap_lines_button_toggled"] +[connection signal="text_changed" from="Editor/DefaultCSVLocale" to="." method="_on_default_csv_locale_text_changed"] +[connection signal="toggled" from="Runtime/IncludeAllResponsesButton" to="." method="_on_include_all_responses_button_toggled"] +[connection signal="toggled" from="Runtime/IgnoreMissingStateValues" to="." method="_on_ignore_missing_state_values_toggled"] +[connection signal="pressed" from="Runtime/CustomBalloon/RevertBalloonPath" to="." method="_on_revert_balloon_path_pressed"] +[connection signal="pressed" from="Runtime/CustomBalloon/LoadBalloonPath" to="." method="_on_load_balloon_path_pressed"] +[connection signal="button_clicked" from="Runtime/GlobalsList" to="." method="_on_globals_list_button_clicked"] +[connection signal="item_selected" from="Runtime/GlobalsList" to="." method="_on_globals_list_item_selected"] +[connection signal="toggled" from="Advanced/CheckForUpdates" to="." method="_on_keep_up_to_date_toggled"] +[connection signal="toggled" from="Advanced/IncludeCharactersInTranslations" to="." method="_on_include_characters_in_translations_toggled"] +[connection signal="toggled" from="Advanced/IncludeNotesInTranslations" to="." method="_on_include_notes_in_translations_toggled"] +[connection signal="toggled" from="Advanced/OpenInExternalEditorButton" to="." method="_on_open_in_external_editor_button_toggled"] +[connection signal="pressed" from="Advanced/CustomTestScene/RevertTestScene" to="." method="_on_revert_test_scene_pressed"] +[connection signal="pressed" from="Advanced/CustomTestScene/LoadTestScene" to="." method="_on_load_test_scene_pressed"] +[connection signal="toggled" from="Advanced/MissingTranslationsButton" to="." method="_on_missing_translations_button_toggled"] +[connection signal="toggled" from="Advanced/CreateLinesForResponseCharacters" to="." method="_on_create_lines_for_response_characters_toggled"] +[connection signal="file_selected" from="CustomTestSceneFileDialog" to="." method="_on_custom_test_scene_file_dialog_file_selected"] diff --git a/project.godot b/project.godot index b834fbd..5f834c1 100644 --- a/project.godot +++ b/project.godot @@ -15,6 +15,11 @@ run/main_scene="res://src/main/main.tscn" config/features=PackedStringArray("4.2", "GL Compatibility") config/icon="res://icon.svg" +[autoload] + +DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd" +PlayerState="*res://src/autoloads/player_state.gd" + [display] window/size/viewport_width=256 @@ -24,8 +29,26 @@ window/size/window_height_override=720 window/stretch/mode="viewport" window/stretch/scale_mode="integer" +[editor_plugins] + +enabled=PackedStringArray("res://addons/dialogue_manager/plugin.cfg") + [input] +ui_accept={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194309,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194310,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":32,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) +] +} +ui_cancel={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194305,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":88,"key_label":0,"unicode":120,"echo":false,"script":null) +] +} interact={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) @@ -37,6 +60,14 @@ adv_text={ ] } +[internationalization] + +locale/translations_pot_files=PackedStringArray("res://src/dialogue/main.dialogue") + +[layer_names] + +2d_physics/layer_1="actionables" + [rendering] textures/canvas_textures/default_texture_filter=0 diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd new file mode 100644 index 0000000..624ffcf --- /dev/null +++ b/src/autoloads/player_state.gd @@ -0,0 +1,21 @@ +extends Node + +# these are functions that can be called in the dialog system + +func has_boots(): + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + return player.has_boots + +func give_boots(): + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + player.give_boots() + var ui = current_scene.get_node("UI") + ui.bootIcon.visible = true + + + +# ion know what this returns +func _get_current_scene(): + return get_tree().get_root().get_children()[2] diff --git a/src/dialogue/main.dialogue b/src/dialogue/main.dialogue new file mode 100644 index 0000000..4fbb0b7 --- /dev/null +++ b/src/dialogue/main.dialogue @@ -0,0 +1,11 @@ +~ start + +if PlayerState.has_boots() == false + The chest contained boots. + do PlayerState.give_boots() + They fit you perfectly. (did you see the change in the ui!?!?) + An air of unease overwhelms you. + Something is wrong... +else: + You already took the boots. Nothing has been added in between then and now. +=> END \ No newline at end of file diff --git a/src/dialogue/main.dialogue.import b/src/dialogue/main.dialogue.import new file mode 100644 index 0000000..48041f3 --- /dev/null +++ b/src/dialogue/main.dialogue.import @@ -0,0 +1,15 @@ +[remap] + +importer="dialogue_manager_compiler_11" +type="Resource" +uid="uid://dlw5a1hy61hj8" +path="res://.godot/imported/main.dialogue-149136ebb6b3f65449302c7d610ce455.tres" + +[deps] + +source_file="res://src/dialogue/main.dialogue" +dest_files=["res://.godot/imported/main.dialogue-149136ebb6b3f65449302c7d610ce455.tres"] + +[params] + +defaults=true diff --git a/src/main/main.gd b/src/main/main.gd index eabe0e6..38ff892 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -12,6 +12,7 @@ var map_room_id_dict: Dictionary = { #Not perfect but works for time constraint 2: preload('res://src/maps/map-2.tscn'), 3: preload('res://src/maps/map-3.tscn') } + var shuffled_maps:Array = [] var current_map_id diff --git a/src/maps/map-1.tscn b/src/maps/map-1.tscn index 52d3adf..7459311 100644 --- a/src/maps/map-1.tscn +++ b/src/maps/map-1.tscn @@ -1,8 +1,10 @@ -[gd_scene load_steps=4 format=3 uid="uid://deqm4to4ptnq0"] +[gd_scene load_steps=6 format=3 uid="uid://deqm4to4ptnq0"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_vosps"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_web8r"] [ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_8x2ye"] +[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="4_hq2kf"] +[ext_resource type="Resource" uid="uid://dlw5a1hy61hj8" path="res://src/dialogue/main.dialogue" id="5_gjl3f"] [node name="Map" type="Node2D"] script = ExtResource("1_web8r") @@ -11,7 +13,7 @@ script = ExtResource("1_web8r") tile_set = ExtResource("1_vosps") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 196615, 3, 262144) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -20,3 +22,7 @@ position = Vector2(80, 48) [node name="stairs" parent="." instance=ExtResource("3_8x2ye")] position = Vector2(160, 96) toward_room_id = 2 + +[node name="Chest" parent="." instance=ExtResource("4_hq2kf")] +position = Vector2(112, 64) +dialog_resource = ExtResource("5_gjl3f") diff --git a/src/maps/map-4.tscn b/src/maps/map-4.tscn new file mode 100644 index 0000000..55e1f6a --- /dev/null +++ b/src/maps/map-4.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=3 format=3 uid="uid://22clf0thbdqv"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_qwjcs"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_1bcx7"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_qwjcs") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_1bcx7") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 196615, 3, 262144, 393226, 3, 196608) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 48) diff --git a/src/player/player.gd b/src/player/player.gd index 6929468..c744812 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -33,16 +33,13 @@ func get_input_vector(event: InputEvent) -> Vector2: return dir -func _input(event: InputEvent) -> void: - # don't do anything if you aren't allowed to - if !is_actionable: - return +func _unhandled_input(event: InputEvent) -> void: var _input_dir := get_input_vector(event) #check what group the next tile is in based on your raycast if _input_dir != Vector2.ZERO: _move(_input_dir) return - if event.is_action_pressed('interact'): + if event.is_action_pressed('ui_accept'): _interact() @@ -72,3 +69,7 @@ func _interact() -> void: if interact_tile.is_in_group('interact'): interact_tile._on_interaction(self) +func give_boots(): + var boots = boots_packed_scene.instantiate() + add_child(boots) + has_boots = true \ No newline at end of file diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 643a03b..207ee78 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -1,11 +1,15 @@ extends Area2D signal inspected + +@export var dialog_resource: DialogueResource +@export var dialog_start: String = "start" + var opened:bool = false @onready var sprite = $Sprite2D #bad solution but not a bad solution YET -@onready var ui:UI = get_parent().get_parent().get_parent().get_node('UI') +@onready var ui:UI = get_parent().get_parent().get_node('UI') func _init() -> void: add_to_group('interact') @@ -15,24 +19,30 @@ func _ready() -> void: pass func _on_interaction(player:Player) -> void: - if !opened: - opened = true - - # we should make a generic chest with the ability to give any item (although we'd need to have some sort of item data strucutre) - if !player.has_boots: - print('boots') - var boots = player.boots_packed_scene.instantiate() - player.add_child(boots) - player.has_boots = true - - ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) - $Sprite2D.frame = 1 - - # added a cheeky placeholder if statement for when the player is already wearing boots and opens a new chest - # did it for shits and giggles - elif player.has_boots: - print('boots again?') - - ui.render_text(['The chest contained the same boots.', "The ones you're already wearing.", 'You don\'t need them right now.']) + if dialog_resource == null: + # we need 404.dialog lol + return + + DialogueManager.show_example_dialogue_balloon(load("res://src/dialogue/main.dialogue"),"start") + $Sprite2D.frame = 1 + + #if !opened: + #opened = true + + ## we should make a generic chest with the ability to give any item (although we'd need to have some sort of item data strucutre) + #if !player.has_boots: + #print('boots') + #var boots = player.boots_packed_scene.instantiate() + #player.add_child(boots) + #player.has_boots = true + + #ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) + + ## added a cheeky placeholder if statement for when the player is already wearing boots and opens a new chest + ## did it for shits and giggles + #elif player.has_boots: + #print('boots again?') + + #ui.render_text(['The chest contained the same boots.', "The ones you're already wearing.", 'You don\'t need them right now.']) diff --git a/src/scene-tiles/chest/chest.tscn b/src/scene-tiles/chest/chest.tscn index 9d1385c..97d3972 100644 --- a/src/scene-tiles/chest/chest.tscn +++ b/src/scene-tiles/chest/chest.tscn @@ -10,10 +10,12 @@ size = Vector2(16, 16) script = ExtResource("1_j2k5u") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(8, 8) shape = SubResource("RectangleShape2D_vdfc5") [node name="Sprite2D" type="Sprite2D" parent="."] texture = ExtResource("1_dpxiw") +centered = false hframes = 2 region_enabled = true region_rect = Rect2(128, 96, 32, 16) From 55bcbf075fc0984736e85de5fa807ab73b6498b9 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Thu, 11 Apr 2024 11:10:27 -0400 Subject: [PATCH 50/86] what is happening --- src/autoloads/player_state.gd | 19 +++++-------------- src/dialogue/main.dialogue | 3 ++- src/scene-tiles/chest/chest.gd | 23 ++++------------------- 3 files changed, 11 insertions(+), 34 deletions(-) diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd index 624ffcf..b432bc0 100644 --- a/src/autoloads/player_state.gd +++ b/src/autoloads/player_state.gd @@ -1,21 +1,12 @@ extends Node -# these are functions that can be called in the dialog system +#can you use an onready in a autoload? when is an autoload put in the scene??? func has_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - return player.has_boots - -func give_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - player.give_boots() - var ui = current_scene.get_node("UI") - ui.bootIcon.visible = true - - + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + return player.has_boots # ion know what this returns func _get_current_scene(): - return get_tree().get_root().get_children()[2] + return get_tree().get_root().get_children()[0] diff --git a/src/dialogue/main.dialogue b/src/dialogue/main.dialogue index 4fbb0b7..6968a02 100644 --- a/src/dialogue/main.dialogue +++ b/src/dialogue/main.dialogue @@ -1,8 +1,9 @@ ~ start if PlayerState.has_boots() == false + change from vscode The chest contained boots. - do PlayerState.give_boots() + do PlayerState._give_boots() They fit you perfectly. (did you see the change in the ui!?!?) An air of unease overwhelms you. Something is wrong... diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 207ee78..4cb98a8 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -23,26 +23,11 @@ func _on_interaction(player:Player) -> void: # we need 404.dialog lol return + if opened: + return + + opened = true DialogueManager.show_example_dialogue_balloon(load("res://src/dialogue/main.dialogue"),"start") $Sprite2D.frame = 1 - #if !opened: - #opened = true - - ## we should make a generic chest with the ability to give any item (although we'd need to have some sort of item data strucutre) - #if !player.has_boots: - #print('boots') - #var boots = player.boots_packed_scene.instantiate() - #player.add_child(boots) - #player.has_boots = true - - #ui.render_text(['The chest contained boots.',"They fit you perfectly.",'The chest also contained a note:','"SOMEONE ADD SONGBOOT NOISES ALREADY!!!"',"You don't think the note was addressing you."]) - - ## added a cheeky placeholder if statement for when the player is already wearing boots and opens a new chest - ## did it for shits and giggles - #elif player.has_boots: - #print('boots again?') - - #ui.render_text(['The chest contained the same boots.', "The ones you're already wearing.", 'You don\'t need them right now.']) - From 2b99e40c2b0d94b87c25e9e8da13283b753535bb Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Thu, 11 Apr 2024 11:19:31 -0400 Subject: [PATCH 51/86] thing should behave? --- project.godot | 2 +- src/autoloads/player_state.gd | 19 ++++++++++++++----- src/dialogue/main.dialogue | 1 - 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/project.godot b/project.godot index 5f834c1..0c34852 100644 --- a/project.godot +++ b/project.godot @@ -18,7 +18,7 @@ config/icon="res://icon.svg" [autoload] DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd" -PlayerState="*res://src/autoloads/player_state.gd" +PlayerState="res://src/autoloads/player_state.gd" [display] diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd index b432bc0..ed93a91 100644 --- a/src/autoloads/player_state.gd +++ b/src/autoloads/player_state.gd @@ -1,12 +1,21 @@ extends Node -#can you use an onready in a autoload? when is an autoload put in the scene??? +# these are functions that can be called in the dialog system func has_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - return player.has_boots + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + return player.has_boots + +func _give_boots(): + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + player.give_boots() + var ui = current_scene.get_node("UI") + ui.bootIcon.visible = true + + # ion know what this returns func _get_current_scene(): - return get_tree().get_root().get_children()[0] + return get_tree().get_root().get_children()[2] \ No newline at end of file diff --git a/src/dialogue/main.dialogue b/src/dialogue/main.dialogue index 6968a02..e735370 100644 --- a/src/dialogue/main.dialogue +++ b/src/dialogue/main.dialogue @@ -1,7 +1,6 @@ ~ start if PlayerState.has_boots() == false - change from vscode The chest contained boots. do PlayerState._give_boots() They fit you perfectly. (did you see the change in the ui!?!?) From 1214f6a1cae464cbce0898a4e1350a4789dd9c6a Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Thu, 11 Apr 2024 12:16:09 -0400 Subject: [PATCH 52/86] addon makes it brokey --- .gitignore | 2 + addons/dialogue_manager/DialogueManager.cs | 394 ---- addons/dialogue_manager/LICENSE | 21 - addons/dialogue_manager/assets/icon.svg | 52 - .../dialogue_manager/assets/icon.svg.import | 38 - .../assets/responses_menu.svg | 52 - .../assets/responses_menu.svg.import | 38 - addons/dialogue_manager/assets/update.svg | 71 - .../dialogue_manager/assets/update.svg.import | 37 - .../dialogue_manager/components/code_edit.gd | 425 ---- .../components/code_edit.tscn | 56 - .../code_edit_syntax_highlighter.gd | 382 ---- .../components/dialogue_cache.gd | 160 -- .../components/download_update_panel.gd | 84 - .../components/download_update_panel.tscn | 60 - .../components/errors_panel.gd | 85 - .../components/errors_panel.tscn | 56 - .../dialogue_manager/components/files_list.gd | 144 -- .../components/files_list.tscn | 40 - .../components/find_in_files.gd | 229 --- .../components/find_in_files.tscn | 139 -- .../components/parse_result.gd | 10 - addons/dialogue_manager/components/parser.gd | 1780 ----------------- .../components/resolved_line_data.gd | 15 - .../components/resolved_tag_data.gd | 10 - .../components/search_and_replace.gd | 210 -- .../components/search_and_replace.tscn | 87 - .../dialogue_manager/components/title_list.gd | 67 - .../components/title_list.tscn | 45 - .../components/update_button.gd | 126 -- .../components/update_button.tscn | 42 - addons/dialogue_manager/constants.gd | 187 -- addons/dialogue_manager/dialogue_label.gd | 226 --- addons/dialogue_manager/dialogue_label.tscn | 19 - addons/dialogue_manager/dialogue_line.gd | 98 - addons/dialogue_manager/dialogue_manager.gd | 1235 ------------ .../dialogue_reponses_menu.gd | 131 -- addons/dialogue_manager/dialogue_resource.gd | 42 - addons/dialogue_manager/dialogue_response.gd | 62 - .../editor_translation_parser_plugin.gd | 43 - .../example_balloon/ExampleBalloon.cs | 204 -- .../example_balloon/example_balloon.gd | 141 -- .../example_balloon/example_balloon.tscn | 149 -- .../small_example_balloon.tscn | 173 -- addons/dialogue_manager/import_plugin.gd | 113 -- addons/dialogue_manager/l10n/en.mo | Bin 9770 -> 0 bytes addons/dialogue_manager/l10n/en.po | 481 ----- addons/dialogue_manager/l10n/es.po | 457 ----- addons/dialogue_manager/l10n/translations.pot | 471 ----- addons/dialogue_manager/l10n/zh.po | 408 ---- addons/dialogue_manager/l10n/zh_TW.po | 408 ---- addons/dialogue_manager/plugin.cfg | 7 - addons/dialogue_manager/plugin.gd | 276 --- addons/dialogue_manager/settings.gd | 184 -- addons/dialogue_manager/test_scene.gd | 31 - addons/dialogue_manager/test_scene.tscn | 7 - addons/dialogue_manager/utilities/builtins.gd | 468 ----- addons/dialogue_manager/views/main_view.gd | 1100 ---------- addons/dialogue_manager/views/main_view.tscn | 334 ---- .../dialogue_manager/views/settings_view.gd | 280 --- .../dialogue_manager/views/settings_view.tscn | 221 -- 61 files changed, 2 insertions(+), 12911 deletions(-) delete mode 100644 addons/dialogue_manager/DialogueManager.cs delete mode 100644 addons/dialogue_manager/LICENSE delete mode 100644 addons/dialogue_manager/assets/icon.svg delete mode 100644 addons/dialogue_manager/assets/icon.svg.import delete mode 100644 addons/dialogue_manager/assets/responses_menu.svg delete mode 100644 addons/dialogue_manager/assets/responses_menu.svg.import delete mode 100644 addons/dialogue_manager/assets/update.svg delete mode 100644 addons/dialogue_manager/assets/update.svg.import delete mode 100644 addons/dialogue_manager/components/code_edit.gd delete mode 100644 addons/dialogue_manager/components/code_edit.tscn delete mode 100644 addons/dialogue_manager/components/code_edit_syntax_highlighter.gd delete mode 100644 addons/dialogue_manager/components/dialogue_cache.gd delete mode 100644 addons/dialogue_manager/components/download_update_panel.gd delete mode 100644 addons/dialogue_manager/components/download_update_panel.tscn delete mode 100644 addons/dialogue_manager/components/errors_panel.gd delete mode 100644 addons/dialogue_manager/components/errors_panel.tscn delete mode 100644 addons/dialogue_manager/components/files_list.gd delete mode 100644 addons/dialogue_manager/components/files_list.tscn delete mode 100644 addons/dialogue_manager/components/find_in_files.gd delete mode 100644 addons/dialogue_manager/components/find_in_files.tscn delete mode 100644 addons/dialogue_manager/components/parse_result.gd delete mode 100644 addons/dialogue_manager/components/parser.gd delete mode 100644 addons/dialogue_manager/components/resolved_line_data.gd delete mode 100644 addons/dialogue_manager/components/resolved_tag_data.gd delete mode 100644 addons/dialogue_manager/components/search_and_replace.gd delete mode 100644 addons/dialogue_manager/components/search_and_replace.tscn delete mode 100644 addons/dialogue_manager/components/title_list.gd delete mode 100644 addons/dialogue_manager/components/title_list.tscn delete mode 100644 addons/dialogue_manager/components/update_button.gd delete mode 100644 addons/dialogue_manager/components/update_button.tscn delete mode 100644 addons/dialogue_manager/constants.gd delete mode 100644 addons/dialogue_manager/dialogue_label.gd delete mode 100644 addons/dialogue_manager/dialogue_label.tscn delete mode 100644 addons/dialogue_manager/dialogue_line.gd delete mode 100644 addons/dialogue_manager/dialogue_manager.gd delete mode 100644 addons/dialogue_manager/dialogue_reponses_menu.gd delete mode 100644 addons/dialogue_manager/dialogue_resource.gd delete mode 100644 addons/dialogue_manager/dialogue_response.gd delete mode 100644 addons/dialogue_manager/editor_translation_parser_plugin.gd delete mode 100644 addons/dialogue_manager/example_balloon/ExampleBalloon.cs delete mode 100644 addons/dialogue_manager/example_balloon/example_balloon.gd delete mode 100644 addons/dialogue_manager/example_balloon/example_balloon.tscn delete mode 100644 addons/dialogue_manager/example_balloon/small_example_balloon.tscn delete mode 100644 addons/dialogue_manager/import_plugin.gd delete mode 100644 addons/dialogue_manager/l10n/en.mo delete mode 100644 addons/dialogue_manager/l10n/en.po delete mode 100644 addons/dialogue_manager/l10n/es.po delete mode 100644 addons/dialogue_manager/l10n/translations.pot delete mode 100644 addons/dialogue_manager/l10n/zh.po delete mode 100644 addons/dialogue_manager/l10n/zh_TW.po delete mode 100644 addons/dialogue_manager/plugin.cfg delete mode 100644 addons/dialogue_manager/plugin.gd delete mode 100644 addons/dialogue_manager/settings.gd delete mode 100644 addons/dialogue_manager/test_scene.gd delete mode 100644 addons/dialogue_manager/test_scene.tscn delete mode 100644 addons/dialogue_manager/utilities/builtins.gd delete mode 100644 addons/dialogue_manager/views/main_view.gd delete mode 100644 addons/dialogue_manager/views/main_view.tscn delete mode 100644 addons/dialogue_manager/views/settings_view.gd delete mode 100644 addons/dialogue_manager/views/settings_view.tscn diff --git a/.gitignore b/.gitignore index 75eb8af..f0e8e76 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ # Godot 4+ specific ignores .godot/ .vscode/settings.json +# don't keep the addons in the repo +addons/ \ No newline at end of file diff --git a/addons/dialogue_manager/DialogueManager.cs b/addons/dialogue_manager/DialogueManager.cs deleted file mode 100644 index ae4f931..0000000 --- a/addons/dialogue_manager/DialogueManager.cs +++ /dev/null @@ -1,394 +0,0 @@ -using Godot; -using Godot.Collections; -using System; -using System.Reflection; -using System.Threading.Tasks; - -#nullable enable - -namespace DialogueManagerRuntime -{ - public enum TranslationSource - { - None, - Guess, - CSV, - PO - } - - public partial class DialogueManager : Node - { - public delegate void PassedTitleEventHandler(string title); - public delegate void GotDialogueEventHandler(DialogueLine dialogueLine); - public delegate void MutatedEventHandler(Dictionary mutation); - public delegate void DialogueEndedEventHandler(Resource dialogueResource); - - public static PassedTitleEventHandler? PassedTitle; - public static GotDialogueEventHandler? GotDialogue; - public static MutatedEventHandler? Mutated; - public static DialogueEndedEventHandler? DialogueEnded; - - [Signal] public delegate void ResolvedEventHandler(Variant value); - - private static GodotObject? instance; - public static GodotObject Instance - { - get - { - if (instance == null) - { - instance = Engine.GetSingleton("DialogueManager"); - } - return instance; - } - } - - - public static Godot.Collections.Array GameStates - { - get => (Godot.Collections.Array)Instance.Get("game_states"); - set => Instance.Set("game_states", value); - } - - - public static bool IncludeSingletons - { - get => (bool)Instance.Get("include_singletons"); - set => Instance.Set("include_singletons", value); - } - - - public static bool IncludeClasses - { - get => (bool)Instance.Get("include_classes"); - set => Instance.Set("include_classes", value); - } - - - public static TranslationSource TranslationSource - { - get => (TranslationSource)(int)Instance.Get("translation_source"); - set => Instance.Set("translation_source", (int)value); - } - - - public static Func<Node> GetCurrentScene - { - set => Instance.Set("get_current_scene", Callable.From(value)); - } - - - public void Prepare() - { - Instance.Connect("passed_title", Callable.From((string title) => PassedTitle?.Invoke(title))); - Instance.Connect("got_dialogue", Callable.From((RefCounted line) => GotDialogue?.Invoke(new DialogueLine(line)))); - Instance.Connect("mutated", Callable.From((Dictionary mutation) => Mutated?.Invoke(mutation))); - Instance.Connect("dialogue_ended", Callable.From((Resource dialogueResource) => DialogueEnded?.Invoke(dialogueResource))); - } - - - public static async Task<GodotObject> GetSingleton() - { - if (instance != null) return instance; - - var tree = Engine.GetMainLoop(); - int x = 0; - - // Try and find the singleton for a few seconds - while (!Engine.HasSingleton("DialogueManager") && x < 300) - { - await tree.ToSignal(tree, SceneTree.SignalName.ProcessFrame); - x++; - } - - // If it times out something is wrong - if (x >= 300) - { - throw new Exception("The DialogueManager singleton is missing."); - } - - instance = Engine.GetSingleton("DialogueManager"); - return instance; - } - - public static async Task<DialogueLine?> GetNextDialogueLine(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - Instance.Call("_bridge_get_next_dialogue_line", dialogueResource, key, extraGameStates ?? new Array<Variant>()); - var result = await Instance.ToSignal(Instance, "bridge_get_next_dialogue_line_completed"); - - if ((RefCounted)result[0] == null) return null; - - return new DialogueLine((RefCounted)result[0]); - } - - - public static CanvasLayer ShowExampleDialogueBalloon(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - return (CanvasLayer)Instance.Call("show_example_dialogue_balloon", dialogueResource, key, extraGameStates ?? new Array<Variant>()); - } - - - public static Node ShowDialogueBalloonScene(string balloonScene, Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array<Variant>()); - } - - public static Node ShowDialogueBalloonScene(PackedScene balloonScene, Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array<Variant>()); - } - - public static Node ShowDialogueBalloonScene(Node balloonScene, Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - return (Node)Instance.Call("show_dialogue_balloon_scene", balloonScene, dialogueResource, key, extraGameStates ?? new Array<Variant>()); - } - - - public static Node ShowDialogueBalloon(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null) - { - return (Node)Instance.Call("show_dialogue_balloon", dialogueResource, key, extraGameStates ?? new Array<Variant>()); - } - - - public static async void Mutate(Dictionary mutation, Array<Variant>? extraGameStates = null, bool isInlineMutation = false) - { - Instance.Call("_bridge_mutate", mutation, extraGameStates ?? new Array<Variant>(), isInlineMutation); - await Instance.ToSignal(Instance, "bridge_mutated"); - } - - - public bool ThingHasMethod(GodotObject thing, string method) - { - MethodInfo? info = thing.GetType().GetMethod(method, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); - return info != null; - } - - - public async void ResolveThingMethod(GodotObject thing, string method, Array<Variant> args) - { - MethodInfo? info = thing.GetType().GetMethod(method, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); - - if (info == null) return; - -#nullable disable - // Convert the method args to something reflection can handle - ParameterInfo[] argTypes = info.GetParameters(); - object[] _args = new object[argTypes.Length]; - for (int i = 0; i < argTypes.Length; i++) - { - if (i < args.Count && args[i].Obj != null) - { - _args[i] = Convert.ChangeType(args[i].Obj, argTypes[i].ParameterType); - } - else if (argTypes[i].DefaultValue != null) - { - _args[i] = argTypes[i].DefaultValue; - } - } - - // Add a single frame wait in case the method returns before signals can listen - await ToSignal(Engine.GetMainLoop(), SceneTree.SignalName.ProcessFrame); - - if (info.ReturnType == typeof(Task)) - { - await (Task)info.Invoke(thing, _args); - EmitSignal(SignalName.Resolved, null); - } - else - { - var value = (Variant)info.Invoke(thing, _args); - EmitSignal(SignalName.Resolved, value); - } - } -#nullable enable - } - - - public partial class DialogueLine : RefCounted - { - private string type = "dialogue"; - public string Type - { - get => type; - set => type = value; - } - - private string next_id = ""; - public string NextId - { - get => next_id; - set => next_id = value; - } - - private string character = ""; - public string Character - { - get => character; - set => character = value; - } - - private string text = ""; - public string Text - { - get => text; - set => text = value; - } - - private string translation_key = ""; - public string TranslationKey - { - get => translation_key; - set => translation_key = value; - } - - private Array<DialogueResponse> responses = new Array<DialogueResponse>(); - public Array<DialogueResponse> Responses - { - get => responses; - } - - private string? time = null; - public string? Time - { - get => time; - } - - private Dictionary pauses = new Dictionary(); - public Dictionary Pauses - { - get => pauses; - } - - private Dictionary speeds = new Dictionary(); - public Dictionary Speeds - { - get => speeds; - } - - private Array<Godot.Collections.Array> inline_mutations = new Array<Godot.Collections.Array>(); - public Array<Godot.Collections.Array> InlineMutations - { - get => inline_mutations; - } - - private Array<Variant> extra_game_states = new Array<Variant>(); - - private Array<string> tags = new Array<string>(); - public Array<string> Tags - { - get => tags; - } - - public DialogueLine(RefCounted data) - { - type = (string)data.Get("type"); - next_id = (string)data.Get("next_id"); - character = (string)data.Get("character"); - text = (string)data.Get("text"); - translation_key = (string)data.Get("translation_key"); - pauses = (Dictionary)data.Get("pauses"); - speeds = (Dictionary)data.Get("speeds"); - inline_mutations = (Array<Godot.Collections.Array>)data.Get("inline_mutations"); - time = (string)data.Get("time"); - tags = (Array<string>)data.Get("tags"); - - foreach (var response in (Array<RefCounted>)data.Get("responses")) - { - responses.Add(new DialogueResponse(response)); - } - } - - - public string GetTagValue(string tagName) - { - string wrapped = $"{tagName}="; - foreach (var tag in tags) - { - if (tag.StartsWith(wrapped)) - { - return tag.Substring(wrapped.Length); - } - } - return ""; - } - - public override string ToString() - { - switch (type) - { - case "dialogue": - return $"<DialogueLine character=\"{character}\" text=\"{text}\">"; - case "mutation": - return "<DialogueLine mutation>"; - default: - return ""; - } - } - } - - - public partial class DialogueResponse : RefCounted - { - private string next_id = ""; - public string NextId - { - get => next_id; - set => next_id = value; - } - - private bool is_allowed = true; - public bool IsAllowed - { - get => is_allowed; - set => is_allowed = value; - } - - private string text = ""; - public string Text - { - get => text; - set => text = value; - } - - private string translation_key = ""; - public string TranslationKey - { - get => translation_key; - set => translation_key = value; - } - - private Array<string> tags = new Array<string>(); - public Array<string> Tags - { - get => tags; - } - - public DialogueResponse(RefCounted data) - { - next_id = (string)data.Get("next_id"); - is_allowed = (bool)data.Get("is_allowed"); - text = (string)data.Get("text"); - translation_key = (string)data.Get("translation_key"); - tags = (Array<string>)data.Get("tags"); - } - - public string GetTagValue(string tagName) - { - string wrapped = $"{tagName}="; - foreach (var tag in tags) - { - if (tag.StartsWith(wrapped)) - { - return tag.Substring(wrapped.Length); - } - } - return ""; - } - - public override string ToString() - { - return $"<DialogueResponse text=\"{text}\""; - } - } -} - diff --git a/addons/dialogue_manager/LICENSE b/addons/dialogue_manager/LICENSE deleted file mode 100644 index 4167139..0000000 --- a/addons/dialogue_manager/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -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. diff --git a/addons/dialogue_manager/assets/icon.svg b/addons/dialogue_manager/assets/icon.svg deleted file mode 100644 index e3b2d4f..0000000 --- a/addons/dialogue_manager/assets/icon.svg +++ /dev/null @@ -1,52 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - width="16" - height="16" - viewBox="0 0 4.2333333 4.2333335" - version="1.1" - id="svg291" - inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" - sodipodi:docname="icon.svg" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg"> - <sodipodi:namedview - id="namedview293" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageshadow="2" - inkscape:pageopacity="0.0" - inkscape:pagecheckerboard="0" - inkscape:document-units="px" - showgrid="false" - width="1920px" - units="px" - borderlayer="true" - inkscape:showpageshadow="false" - inkscape:zoom="18.583334" - inkscape:cx="9.3901342" - inkscape:cy="13.506726" - inkscape:window-width="1440" - inkscape:window-height="890" - inkscape:window-x="-6" - inkscape:window-y="-6" - inkscape:window-maximized="1" - inkscape:current-layer="layer1" - inkscape:deskcolor="#d1d1d1" /> - <defs - id="defs288" /> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1"> - <path - id="path3615" - style="clip-rule:evenodd;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.00206088;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:40" - d="M 2.3616237,0.32495581 C 2.2890187,0.32469635 2.2284054,0.32546079 2.1926162,0.32687081 1.8949218,0.33860011 1.5033325,0.34148331 1.2561323,0.35080961 1.1421362,0.35510961 0.51253678,0.28342811 0.31150932,0.54279835 0.0999174,0.81580911 0.23804642,2.0559707 0.22102032,2.2314376 0.21014342,2.34358 0.20066442,2.896122 0.41300909,3.1219592 0.60816171,3.3295105 0.90177008,3.3453424 0.95593994,3.3503348 1.0177384,3.3560148 1.5339832,3.3499581 1.574996,3.351287 c 0.015313,4.929e-4 0.064365,0.00139 0.1311843,0.00287 0.027454,0.1558591 0.1348816,0.4055146 0.2891801,0.5079801 0.1737371,0.1153709 0.5840376,0.1672049 0.633898,0.1417174 0.033884,-0.017324 0.2120976,-0.020746 0.2120976,-0.03926 -3e-7,-0.00281 -0.1359618,-0.075872 -0.1795407,-0.098149 C 2.5715112,3.8202919 2.5190005,3.7242168 2.4506759,3.6543568 2.4244915,3.6275965 2.4279949,3.4751553 2.4315249,3.3742737 2.5495776,3.3733989 2.8697241,3.3839918 2.9371113,3.3838502 3.0975326,3.3835266 3.5689747,3.3993771 3.8080031,3.1818075 4.0962844,2.9193889 4.0228795,2.3969451 4.0186641,2.3267119 4.013119,2.2343213 4.0250025,1.6246294 4.0162732,1.4864616 4.0028561,1.274529 4.0737709,0.94594107 3.8376871,0.59402732 3.6199123,0.26941205 3.0597025,0.34195584 3.0151516,0.33931907 2.9077682,0.33296522 2.5794394,0.32573415 2.3616237,0.32495581 Z m 0.9580286,0.52713126 a 0.19209624,0.19209624 0 0 1 0.063678,0.007659 A 0.19209624,0.19209624 0 0 1 3.5121209,1.10057 c -0.019132,0.064024 -0.02934,0.114542 -0.029205,0.1517718 a 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.786e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.786e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.786e-4 0.19211544,0.19211544 0 0 0 0,4.784e-4 0.19211544,0.19211544 0 0 0 0,4.785e-4 c -0.00327,0.073938 -0.00815,0.1281478 -0.00336,0.1646986 a 0.19211544,0.19211544 0 0 1 0.00192,0.01963 c 0.00122,0.044001 0.00215,0.096625 -0.00383,0.1560806 a 0.19211544,0.19211544 0 0 1 -0.0091,0.04309 c 0.00152,-0.00444 0.00292,-0.00713 0.00383,-0.00814 0.00239,4.689e-4 -5.16e-5,0.023556 -0.012927,0.069423 l -4.786e-4,0.00144 c -0.00322,0.018276 -0.00512,0.060008 -0.010052,0.1072455 2.1e-6,-1.573e-4 -1.8e-5,0.00348 0,0.00383 8.03e-5,0.00155 -1.3e-6,0.00456 0,0.016278 A 0.19209624,0.19209624 0 0 1 3.256933,2.0270008 0.19209624,0.19209624 0 0 1 3.0649443,1.835012 c -2e-7,-8.421e-4 -2.139e-4,-0.00933 0,-0.025375 a 0.19211544,0.19211544 0 0 1 0.00192,-0.021545 c 0.00393,-0.029738 0.00172,-0.085222 0.018193,-0.1627834 a 0.19211544,0.19211544 0 0 1 0.00336,-0.014841 c -0.00488,0.016544 -0.00842,-0.00696 0.0091,-0.066071 0.00128,-0.023365 8.374e-4,-0.05167 0,-0.083786 5.837e-4,0.00531 0.0012,0.010844 0.00192,0.016278 l -0.00192,-0.020109 c -0.00868,-0.082861 -0.00275,-0.1509043 0,-0.2044368 -3.839e-4,-0.1048643 0.02617,-0.1913531 0.047392,-0.26236915 A 0.19209624,0.19209624 0 0 1 3.3196523,0.85208707 Z M 3.097501,1.5443956 c -3.745e-4,0.00682 -8.326e-4,0.013152 -0.00144,0.019151 l 0.00862,-0.043569 c -0.00298,0.00868 -0.00496,0.016879 -0.00718,0.024418 z M 1.7483131,1.0129554 a 0.19211544,0.19211544 0 0 1 0.1804981,0.1292692 c 0.081754,0.230866 0.1671804,0.4503689 0.2566234,0.6094805 0.060542,-0.039278 0.13119,-0.081733 0.2374723,-0.083307 0.030189,-0.00505 0.059326,-0.01228 0.095756,-0.00527 0.053638,0.010328 0.1089723,0.045047 0.1426749,0.086658 0.067401,0.08322 0.064433,0.1543836 0.063678,0.2082669 -0.00151,0.1077673 -0.021788,0.2137733 -0.022023,0.2044369 A 0.19209624,0.19209624 0 0 1 2.5167468,2.3578344 0.19209624,0.19209624 0 0 1 2.3194915,2.1715908 c -7.704e-4,-0.030281 0.0031,-0.035159 0.00527,-0.059847 -0.035038,0.025653 -0.068601,0.053251 -0.1139486,0.081391 A 0.19211544,0.19211544 0 0 1 1.9704693,2.1624936 c -0.016009,-0.016679 -0.012719,-0.040218 -0.027291,-0.057933 -0.0053,0.038768 -0.013896,0.105592 -0.030642,0.1881586 -0.00975,0.048046 -0.018553,0.093357 -0.036386,0.1412386 -0.00891,0.023941 -0.00752,0.046058 -0.061283,0.09767 -0.00671,0.00645 -0.015395,0.013123 -0.025375,0.020109 -0.00997,0.00699 -0.03579,0.021291 -0.036386,0.021545 -0.00119,5.072e-4 -0.1089417,0.013114 -0.1101182,0.012927 -5.885e-4,-9.26e-5 -0.052085,-0.016004 -0.052666,-0.016278 -5.848e-4,-2.741e-4 -0.028877,-0.016619 -0.039745,-0.025375 -0.021733,-0.017517 -0.036349,-0.03491 -0.045484,-0.048835 a 0.19211544,0.19211544 0 0 1 -0.00718,-0.012927 C 1.405201,2.3135107 1.3718331,2.1230884 1.3226821,1.9293306 1.296257,1.9926645 1.2702556,2.0360279 1.236503,2.1127015 c -0.00662,0.020181 -0.015708,0.041777 -0.033514,0.067986 -0.021835,0.03214 -0.067722,0.078719 -0.1393236,0.090488 -0.0716015,0.011769 -0.13415192,-0.018894 -0.16469865,-0.043568 -0.0305472,-0.024673 -0.042975,-0.046717 -0.0541012,-0.065113 -0.0389429,-0.064387 -0.0578673,-0.09647 -0.0526653,-0.176189 0.002344,0.010422 0.004713,0.021014 0.00718,0.031599 L 0.79602584,1.94896 c -0.001684,0.013201 -0.003086,0.025254 -0.003828,0.036387 C 0.74313508,1.766609 0.72147035,1.582656 0.68734765,1.3720365 A 0.19209624,0.19209624 0 0 1 0.84486459,1.1527576 0.19209624,0.19209624 0 0 1 1.0655799,1.3102746 c 0.012592,0.077723 0.025291,0.1404024 0.035908,0.2097036 0.010745,-0.014664 0.00973,-0.026756 0.021545,-0.041175 -0.0011,-0.00222 0.032336,-0.054265 0.079956,-0.1067668 0.013605,-0.015001 0.028067,-0.03269 0.061762,-0.052665 0.033694,-0.019975 0.1078148,-0.047748 0.1843284,-0.018193 0.068698,0.026536 0.092715,0.077474 0.1086819,0.1139485 -0.00167,-0.078755 -0.00808,-0.1467436 -0.00383,-0.2207153 A 0.19211544,0.19211544 0 0 1 1.7186306,1.0153489 0.19211544,0.19211544 0 0 1 1.748314,1.0129564 Z M 1.2365027,2.1127015 c 0.0015,-0.00457 0.00304,-0.00894 0.00431,-0.013405 l -0.00862,0.02346 c 0.00152,-0.00352 0.00282,-0.00667 0.00431,-0.010052 z M 3.1899043,2.2683033 A 0.19374282,0.20281166 0 0 1 3.3833296,2.4713039 0.19374282,0.20281166 0 0 1 3.1899043,2.6743046 0.19374282,0.20281166 0 0 1 2.9960006,2.4713039 0.19374282,0.20281166 0 0 1 3.1899043,2.2683033 Z" - fill="#E0E0E0" /> - </g> -</svg> diff --git a/addons/dialogue_manager/assets/icon.svg.import b/addons/dialogue_manager/assets/icon.svg.import deleted file mode 100644 index 3b6fd5e..0000000 --- a/addons/dialogue_manager/assets/icon.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://d3lr2uas6ax8v" -path="res://.godot/imported/icon.svg-17eb5d3e2a3cfbe59852220758c5b7bd.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/dialogue_manager/assets/icon.svg" -dest_files=["res://.godot/imported/icon.svg-17eb5d3e2a3cfbe59852220758c5b7bd.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=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/dialogue_manager/assets/responses_menu.svg b/addons/dialogue_manager/assets/responses_menu.svg deleted file mode 100644 index 4e4089d..0000000 --- a/addons/dialogue_manager/assets/responses_menu.svg +++ /dev/null @@ -1,52 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - width="16" - height="16" - viewBox="0 0 4.2333333 4.2333335" - version="1.1" - id="svg291" - inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" - sodipodi:docname="responses_menu.svg" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg"> - <sodipodi:namedview - id="namedview293" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageshadow="2" - inkscape:pageopacity="0.0" - inkscape:pagecheckerboard="0" - inkscape:document-units="px" - showgrid="false" - width="1920px" - units="px" - borderlayer="true" - inkscape:showpageshadow="false" - inkscape:deskcolor="#d1d1d1" - inkscape:zoom="45.254834" - inkscape:cx="7.8334173" - inkscape:cy="6.5959804" - inkscape:window-width="2560" - inkscape:window-height="1377" - inkscape:window-x="-8" - inkscape:window-y="-8" - inkscape:window-maximized="1" - inkscape:current-layer="layer1" /> - <defs - id="defs288" /> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1"> - <path - id="rect181" - style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:1.77487;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill" - d="M 1.5875 0.26458334 L 1.5875 0.79375001 L 4.2333334 0.79375001 L 4.2333334 0.26458334 L 1.5875 0.26458334 z M 0 0.83147381 L 0 2.4189738 L 1.3229167 1.6252238 L 0 0.83147381 z M 1.5875 1.3229167 L 1.5875 1.8520834 L 4.2333334 1.8520834 L 4.2333334 1.3229167 L 1.5875 1.3229167 z M 1.5875 2.38125 L 1.5875 2.9104167 L 4.2333334 2.9104167 L 4.2333334 2.38125 L 1.5875 2.38125 z M 1.5875 3.4395834 L 1.5875 3.9687501 L 4.2333334 3.9687501 L 4.2333334 3.4395834 L 1.5875 3.4395834 z " - fill="#E0E0E0" /> - </g> -</svg> diff --git a/addons/dialogue_manager/assets/responses_menu.svg.import b/addons/dialogue_manager/assets/responses_menu.svg.import deleted file mode 100644 index 83355fc..0000000 --- a/addons/dialogue_manager/assets/responses_menu.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://drjfciwitjm83" -path="res://.godot/imported/responses_menu.svg-87cf63ca685d53616205049572f4eb8f.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/dialogue_manager/assets/responses_menu.svg" -dest_files=["res://.godot/imported/responses_menu.svg-87cf63ca685d53616205049572f4eb8f.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=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/dialogue_manager/assets/update.svg b/addons/dialogue_manager/assets/update.svg deleted file mode 100644 index a5b80ee..0000000 --- a/addons/dialogue_manager/assets/update.svg +++ /dev/null @@ -1,71 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - width="300" - height="80" - viewBox="0 0 79.374999 21.166667" - version="1.1" - id="svg291" - inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" - sodipodi:docname="update.svg" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg"> - <sodipodi:namedview - id="namedview293" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageshadow="2" - inkscape:pageopacity="0.0" - inkscape:pagecheckerboard="0" - inkscape:document-units="px" - showgrid="false" - width="1920px" - units="px" - borderlayer="true" - inkscape:showpageshadow="false" - inkscape:zoom="1" - inkscape:cx="180.5" - inkscape:cy="111" - inkscape:window-width="1440" - inkscape:window-height="890" - inkscape:window-x="-6" - inkscape:window-y="-6" - inkscape:window-maximized="1" - inkscape:current-layer="layer1" - inkscape:deskcolor="#d1d1d1" /> - <defs - id="defs288" /> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1"> - <rect - style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1" - id="rect2462" - width="13.228261" - height="9.4236727" - x="32.95359" - y="4.2143135" - ry="0.90020913" /> - <path - id="path3615" - style="clip-rule:evenodd;fill:#bd93f9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.52916667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:40;stroke-opacity:1;stroke-dasharray:none" - d="m 40.714378,3.0283624 c -0.297691,-0.00106 -0.546217,0.00208 -0.692956,0.00785 -1.220595,0.048091 -2.826171,0.059913 -3.83973,0.098152 -0.467403,0.017637 -3.048858,-0.2762743 -3.873101,0.7871837 -0.867561,1.1193864 -0.301209,6.2042409 -0.371018,6.9236829 -0.04459,0.459801 -0.08346,2.725309 0.787183,3.651277 0.800155,0.850991 2.003996,0.915905 2.2261,0.936375 0.253383,0.02331 2.370068,-0.0015 2.538226,0.0039 0.0628,0.002 0.263908,0.0057 0.537877,0.01177 0.112572,0.639046 0.553034,1.662672 1.185683,2.082798 0.712348,0.473037 2.394644,0.685566 2.599079,0.581063 0.138939,-0.07104 0.869634,-0.08507 0.869634,-0.160971 -2e-6,-0.01157 -0.557466,-0.311089 -0.736145,-0.402428 -0.370261,-0.189241 -0.585564,-0.583165 -0.865705,-0.869601 -0.107353,-0.109727 -0.09299,-0.734754 -0.07851,-1.148384 0.484034,-0.0035 1.796685,0.03983 2.072983,0.03926 0.657753,-0.0013 2.590738,0.06366 3.570791,-0.828408 1.181999,-1.075941 0.881027,-3.218042 0.863743,-3.50601 -0.02274,-0.378815 0.02599,-2.878646 -0.0098,-3.4451551 C 47.443688,6.9217592 47.734446,5.5744981 46.766467,4.1315973 45.873555,2.8006244 43.57661,3.0980651 43.393944,3.087254 42.953654,3.0612024 41.607455,3.0315527 40.714378,3.0283624 Z m 3.928065,2.1613198 a 0.78762433,0.78762433 0 0 1 0.261087,0.031405 0.78762433,0.78762433 0 0 1 0.528062,0.9874148 c -0.07845,0.2625075 -0.120302,0.46964 -0.119753,0.6222881 a 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 0.78770308,0.78770308 0 0 0 0,0.00196 c -0.01334,0.3031554 -0.03341,0.5254256 -0.01373,0.6752895 a 0.78770308,0.78770308 0 0 1 0.0078,0.080487 c 0.0051,0.1804113 0.0088,0.3961799 -0.0157,0.6399549 a 0.78770308,0.78770308 0 0 1 -0.03726,0.1767104 c 0.0063,-0.018206 0.01197,-0.029244 0.0157,-0.033361 0.0098,0.00192 -2.12e-4,0.096583 -0.05301,0.2846419 l -0.002,0.00589 c -0.01314,0.074935 -0.02097,0.2460417 -0.04122,0.4397235 9e-6,-6.455e-4 -7.3e-5,0.014282 0,0.015695 3.29e-4,0.00634 -4e-6,0.018697 0,0.066743 A 0.78762433,0.78762433 0 0 1 44.385285,10.007011 0.78762433,0.78762433 0 0 1 43.598102,9.2198268 c -2e-6,-0.00345 -8.77e-4,-0.038262 0,-0.1040456 a 0.78770308,0.78770308 0 0 1 0.0078,-0.088337 c 0.01609,-0.12193 0.0071,-0.3494247 0.07459,-0.6674374 a 0.78770308,0.78770308 0 0 1 0.01373,-0.060853 c -0.02001,0.067835 -0.03455,-0.028543 0.03731,-0.270902 0.0053,-0.0958 0.0035,-0.2118566 0,-0.3435347 0.0024,0.021788 0.0049,0.044462 0.0078,0.066743 l -0.0078,-0.082447 c -0.03559,-0.3397458 -0.01118,-0.6187306 0,-0.8382225 -0.0016,-0.4299563 0.107334,-0.784574 0.194343,-1.0757507 A 0.78762433,0.78762433 0 0 1 44.642342,5.189683 Z m -0.910856,2.8385724 c -0.0015,0.027966 -0.0033,0.053926 -0.0059,0.078522 l 0.03533,-0.1786397 c -0.01216,0.035586 -0.02031,0.069207 -0.02945,0.100118 z M 38.199709,5.8492675 a 0.78770308,0.78770308 0 0 1 0.740071,0.5300233 c 0.335202,0.9465866 0.685464,1.8465826 1.052196,2.4989649 0.248233,-0.1610476 0.537898,-0.3351164 0.973672,-0.3415703 0.123774,-0.020676 0.243246,-0.050347 0.392613,-0.021583 0.219925,0.042345 0.446803,0.1847018 0.584989,0.3553102 0.276354,0.3412161 0.264185,0.6329968 0.261087,0.8539269 -0.0061,0.4418625 -0.08934,0.8765035 -0.09031,0.8382235 a 0.78762433,0.78762433 0 0 1 -0.763625,0.800915 0.78762433,0.78762433 0 0 1 -0.808777,-0.763625 c -0.0031,-0.124158 0.01275,-0.144159 0.02158,-0.245384 -0.143662,0.105178 -0.281267,0.218336 -0.467201,0.333717 a 0.78770308,0.78770308 0 0 1 -0.985442,-0.125632 c -0.06564,-0.06838 -0.05215,-0.164899 -0.111905,-0.237533 -0.0217,0.158952 -0.05697,0.432943 -0.125637,0.771479 -0.03994,0.196996 -0.07606,0.382777 -0.1492,0.579101 -0.03653,0.09815 -0.03084,0.18885 -0.251272,0.400462 -0.02751,0.02645 -0.06313,0.05381 -0.104038,0.08246 -0.04091,0.02866 -0.146748,0.0873 -0.1492,0.08834 -0.0049,0.0022 -0.446678,0.05377 -0.451502,0.05301 -0.0024,-3.79e-4 -0.213555,-0.06562 -0.215939,-0.06674 -0.0024,-0.0011 -0.118379,-0.06813 -0.162933,-0.104037 -0.08911,-0.07182 -0.149043,-0.143138 -0.186495,-0.20023 a 0.78770308,0.78770308 0 0 1 -0.02945,-0.05301 c -0.380095,-0.694111 -0.516908,-1.474871 -0.718435,-2.269308 -0.108354,0.2596787 -0.214957,0.437476 -0.353349,0.751849 -0.02715,0.08274 -0.06441,0.171293 -0.13741,0.278753 -0.08952,0.131779 -0.277668,0.322761 -0.571248,0.371015 -0.293578,0.04826 -0.550045,-0.07747 -0.67529,-0.178628 C 34.592013,10.728363 34.541064,10.63798 34.495437,10.562564 34.33576,10.298568 34.25817,10.167022 34.2795,9.8401611 c 0.0096,0.042731 0.01942,0.086159 0.02945,0.1295617 L 34.29521,9.6870414 c -0.0069,0.054124 -0.01275,0.1035434 -0.0157,0.1491901 C 34.07835,8.9393633 33.98952,8.1851278 33.849612,7.3215552 a 0.78762433,0.78762433 0 0 1 0.645844,-0.8990776 0.78762433,0.78762433 0 0 1 0.904966,0.645844 c 0.05164,0.3186785 0.103704,0.5756714 0.147218,0.859817 0.04404,-0.060125 0.03987,-0.1097017 0.08834,-0.1688245 -0.0045,-0.0091 0.132583,-0.2224951 0.327832,-0.4377603 0.05578,-0.061504 0.115083,-0.1340347 0.253236,-0.2159342 0.138154,-0.081904 0.442057,-0.1957766 0.755775,-0.074598 0.281673,0.1088032 0.380145,0.3176572 0.445613,0.4672063 -0.0069,-0.3229043 -0.03312,-0.6016714 -0.0157,-0.9049667 a 0.78770308,0.78770308 0 0 1 0.675286,-0.7341808 0.78770308,0.78770308 0 0 1 0.121714,-0.00981 z m -2.098502,4.5091295 c 0.0061,-0.01874 0.01255,-0.03666 0.01766,-0.05496 l -0.03533,0.09619 c 0.0063,-0.01442 0.01158,-0.02735 0.01766,-0.04123 z m 8.00925,0.63799 a 0.79437562,0.83155922 0 0 1 0.793073,0.832334 0.79437562,0.83155922 0 0 1 -0.793073,0.832335 0.79437562,0.83155922 0 0 1 -0.795036,-0.832335 0.79437562,0.83155922 0 0 1 0.795036,-0.832334 z" /> - <path - id="path2353" - style="clip-rule:evenodd;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#4d425c;stroke-width:0.529167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:40;stroke-dasharray:none;stroke-opacity:1" - d="m 40.538948,3.0282389 c -0.29769,-0.00106 -0.546242,0.00198 -0.692981,0.00775 -1.220593,0.048091 -2.826517,0.059946 -3.840075,0.098185 -0.467403,0.017637 -3.048907,-0.2759081 -3.873149,0.7875489 -0.86756,1.1193852 -0.300711,6.2041675 -0.37052,6.9236085 -0.04459,0.4598 -0.08361,2.724973 0.787032,3.65094 0.800154,0.85099 2.004117,0.915907 2.226221,0.936377 0.253382,0.02331 2.369672,-0.0013 2.537829,0.0041 0.0628,0.002 0.263983,0.0058 0.537952,0.01189 0.112572,0.639046 0.553326,1.662435 1.185974,2.082561 0.712347,0.473036 2.394373,0.685862 2.598808,0.58136 0.138939,-0.07104 0.869714,-0.08533 0.869714,-0.161231 -2e-6,-0.01157 -0.55771,-0.31122 -0.736389,-0.402559 -0.370261,-0.189241 -0.585439,-0.582762 -0.86558,-0.869198 -0.107353,-0.109727 -0.09303,-0.735137 -0.07855,-1.148767 0.484033,-0.0035 1.79696,0.03984 2.073258,0.03927 0.657752,-0.0013 2.59079,0.06369 3.570842,-0.828373 1.181997,-1.07594 0.880797,-3.217762 0.863513,-3.505729 -0.02274,-0.378815 0.02597,-2.8787595 -0.0098,-3.4452681 C 47.268006,6.9217821 47.558753,5.5744301 46.590775,4.1315308 45.697864,2.8005592 43.401037,3.0979612 43.218371,3.0871501 42.778082,3.0610985 41.432024,3.0314292 40.538948,3.0282389 Z" /> - <path - id="rect1625" - style="fill:#50fa7b;fill-opacity:1;stroke:#0f451d;stroke-width:0.593381;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" - d="m 50.52517,5.3570989 c -0.643062,0 -1.160653,0.5900216 -1.160653,1.3229166 v 1.0764201 h -1.07642 c -0.732895,0 -1.322916,0.5175908 -1.322916,1.1606533 0,0.643061 0.590021,1.1611691 1.322916,1.1611691 h 1.07642 v 1.076421 c 0,0.732895 0.517591,1.322917 1.160653,1.322917 0.643062,0 1.160653,-0.590022 1.160653,-1.322917 v -1.076421 h 1.076937 c 0.732895,0 1.322916,-0.5181081 1.322916,-1.1611691 0,-0.6430625 -0.590021,-1.1606533 -1.322916,-1.1606533 H 51.685823 V 6.6800155 c 0,-0.732895 -0.517591,-1.3229166 -1.160653,-1.3229166 z" /> - <path - id="path2678" - style="fill:#50fa7b;fill-opacity:1;stroke:#0f451d;stroke-width:0.593381;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" - d="m 57.791691,5.357099 c -0.643062,0 -1.160653,0.5900216 -1.160653,1.3229166 v 1.0764201 h -1.07642 c -0.732895,0 -1.322916,0.5175908 -1.322916,1.1606522 0,0.643062 0.590021,1.1611701 1.322916,1.1611701 h 1.07642 v 1.076421 c 0,0.732895 0.517591,1.322917 1.160653,1.322917 0.643062,0 1.160653,-0.590022 1.160653,-1.322917 v -1.076421 h 1.076937 c 0.732895,0 1.322916,-0.5181081 1.322916,-1.1611701 0,-0.6430614 -0.590021,-1.1606522 -1.322916,-1.1606522 H 58.952344 V 6.6800156 c 0,-0.732895 -0.517591,-1.3229166 -1.160653,-1.3229166 z" /> - </g> -</svg> diff --git a/addons/dialogue_manager/assets/update.svg.import b/addons/dialogue_manager/assets/update.svg.import deleted file mode 100644 index 2d8171a..0000000 --- a/addons/dialogue_manager/assets/update.svg.import +++ /dev/null @@ -1,37 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://d3baj6rygkb3f" -path="res://.godot/imported/update.svg-f1628866ed4eb2e13e3b81f75443687e.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://addons/dialogue_manager/assets/update.svg" -dest_files=["res://.godot/imported/update.svg-f1628866ed4eb2e13e3b81f75443687e.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 diff --git a/addons/dialogue_manager/components/code_edit.gd b/addons/dialogue_manager/components/code_edit.gd deleted file mode 100644 index e57c1af..0000000 --- a/addons/dialogue_manager/components/code_edit.gd +++ /dev/null @@ -1,425 +0,0 @@ -@tool -extends CodeEdit - - -signal active_title_change(title: String) -signal error_clicked(line_number: int) -signal external_file_requested(path: String, title: String) - - -const DialogueSyntaxHighlighter = preload("./code_edit_syntax_highlighter.gd") - - -# A link back to the owner MainView -var main_view - -# Theme overrides for syntax highlighting, etc -var theme_overrides: Dictionary: - set(value): - theme_overrides = value - - syntax_highlighter = DialogueSyntaxHighlighter.new() - - # General UI - add_theme_color_override("font_color", theme_overrides.text_color) - add_theme_color_override("background_color", theme_overrides.background_color) - add_theme_color_override("current_line_color", theme_overrides.current_line_color) - add_theme_font_override("font", get_theme_font("source", "EditorFonts")) - add_theme_font_size_override("font_size", theme_overrides.font_size * theme_overrides.scale) - font_size = round(theme_overrides.font_size) - get: - return theme_overrides - -# Any parse errors -var errors: Array: - set(next_errors): - errors = next_errors - for i in range(0, get_line_count()): - var is_error: bool = false - for error in errors: - if error.line_number == i: - is_error = true - mark_line_as_error(i, is_error) - _on_code_edit_caret_changed() - get: - return errors - -# The last selection (if there was one) so we can remember it for refocusing -var last_selected_text: String - -var font_size: int: - set(value): - font_size = value - add_theme_font_size_override("font_size", font_size * theme_overrides.scale) - get: - return font_size - -var WEIGHTED_RANDOM_PREFIX: RegEx = RegEx.create_from_string("^\\%[\\d.]+\\s") - - -func _ready() -> void: - # Add error gutter - add_gutter(0) - set_gutter_type(0, TextEdit.GUTTER_TYPE_ICON) - - # Add comment delimiter - if not has_comment_delimiter("#"): - add_comment_delimiter("#", "", true) - - syntax_highlighter = DialogueSyntaxHighlighter.new() - - -func _gui_input(event: InputEvent) -> void: - if event is InputEventKey and event.is_pressed(): - match event.as_text(): - "Ctrl+Equal", "Command+Equal": - self.font_size += 1 - get_viewport().set_input_as_handled() - "Ctrl+Minus", "Command+Minus": - self.font_size -= 1 - get_viewport().set_input_as_handled() - "Ctrl+0", "Command+0": - self.font_size = theme_overrides.font_size - get_viewport().set_input_as_handled() - "Ctrl+K", "Command+K": - toggle_comment() - get_viewport().set_input_as_handled() - "Alt+Up": - move_line(-1) - get_viewport().set_input_as_handled() - "Alt+Down": - move_line(1) - get_viewport().set_input_as_handled() - - elif event is InputEventMouse: - match event.as_text(): - "Ctrl+Mouse Wheel Up", "Command+Mouse Wheel Up": - self.font_size += 1 - get_viewport().set_input_as_handled() - "Ctrl+Mouse Wheel Down", "Command+Mouse Wheel Down": - self.font_size -= 1 - get_viewport().set_input_as_handled() - - -func _can_drop_data(at_position: Vector2, data) -> bool: - if typeof(data) != TYPE_DICTIONARY: return false - if data.type != "files": return false - - var files: PackedStringArray = Array(data.files).filter(func(f): return f.get_extension() == "dialogue") - return files.size() > 0 - - -func _drop_data(at_position: Vector2, data) -> void: - var replace_regex: RegEx = RegEx.create_from_string("[^a-zA-Z_0-9]+") - - var files: PackedStringArray = Array(data.files).filter(func(f): return f.get_extension() == "dialogue") - for file in files: - # Don't import the file into itself - if file == main_view.current_file_path: continue - - var path = file.replace("res://", "").replace(".dialogue", "") - # Find the first non-import line in the file to add our import - var lines = text.split("\n") - for i in range(0, lines.size()): - if not lines[i].begins_with("import "): - insert_line_at(i, "import \"%s\" as %s\n" % [file, replace_regex.sub(path, "_", true)]) - set_caret_line(i) - break - - -func _request_code_completion(force: bool) -> void: - var cursor: Vector2 = get_cursor() - var current_line: String = get_line(cursor.y) - - if ("=> " in current_line or "=>< " in current_line) and (cursor.x > current_line.find("=>")): - var prompt: String = current_line.split("=>")[1] - if prompt.begins_with("< "): - prompt = prompt.substr(2) - else: - prompt = prompt.substr(1) - - if "=> " in current_line: - if matches_prompt(prompt, "end"): - add_code_completion_option(CodeEdit.KIND_CLASS, "END", "END".substr(prompt.length()), theme_overrides.text_color, get_theme_icon("Stop", "EditorIcons")) - if matches_prompt(prompt, "end!"): - add_code_completion_option(CodeEdit.KIND_CLASS, "END!", "END!".substr(prompt.length()), theme_overrides.text_color, get_theme_icon("Stop", "EditorIcons")) - - # Get all titles, including those in imports - var parser: DialogueManagerParser = DialogueManagerParser.new() - parser.prepare(text, main_view.current_file_path, false) - for title in parser.titles: - if "/" in title: - var bits = title.split("/") - if matches_prompt(prompt, bits[0]) or matches_prompt(prompt, bits[1]): - add_code_completion_option(CodeEdit.KIND_CLASS, title, title.substr(prompt.length()), theme_overrides.text_color, get_theme_icon("CombineLines", "EditorIcons")) - elif matches_prompt(prompt, title): - add_code_completion_option(CodeEdit.KIND_CLASS, title, title.substr(prompt.length()), theme_overrides.text_color, get_theme_icon("ArrowRight", "EditorIcons")) - update_code_completion_options(true) - parser.free() - return - - var name_so_far: String = WEIGHTED_RANDOM_PREFIX.sub(current_line.strip_edges(), "") - if name_so_far != "" and name_so_far[0].to_upper() == name_so_far[0]: - # Only show names starting with that character - var names: PackedStringArray = get_character_names(name_so_far) - if names.size() > 0: - for name in names: - add_code_completion_option(CodeEdit.KIND_CLASS, name + ": ", name.substr(name_so_far.length()) + ": ", theme_overrides.text_color, get_theme_icon("Sprite2D", "EditorIcons")) - update_code_completion_options(true) - else: - cancel_code_completion() - - -func _filter_code_completion_candidates(candidates: Array) -> Array: - # Not sure why but if this method isn't overridden then all completions are wrapped in quotes. - return candidates - - -func _confirm_code_completion(replace: bool) -> void: - var completion = get_code_completion_option(get_code_completion_selected_index()) - begin_complex_operation() - # Delete any part of the text that we've already typed - for i in range(0, completion.display_text.length() - completion.insert_text.length()): - backspace() - # Insert the whole match - insert_text_at_caret(completion.display_text) - end_complex_operation() - - # Close the autocomplete menu on the next tick - call_deferred("cancel_code_completion") - - -### Helpers - - -# Get the current caret as a Vector2 -func get_cursor() -> Vector2: - return Vector2(get_caret_column(), get_caret_line()) - - -# Set the caret from a Vector2 -func set_cursor(from_cursor: Vector2) -> void: - set_caret_line(from_cursor.y) - set_caret_column(from_cursor.x) - - -# Check if a prompt is the start of a string without actually being that string -func matches_prompt(prompt: String, matcher: String) -> bool: - return prompt.length() < matcher.length() and matcher.to_lower().begins_with(prompt.to_lower()) - - -## Get a list of titles from the current text -func get_titles() -> PackedStringArray: - var titles = PackedStringArray([]) - var lines = text.split("\n") - for line in lines: - if line.begins_with("~ "): - titles.append(line.substr(2).strip_edges()) - return titles - - -## Work out what the next title above the current line is -func check_active_title() -> void: - var line_number = get_caret_line() - var lines = text.split("\n") - # Look at each line above this one to find the next title line - for i in range(line_number, -1, -1): - if lines[i].begins_with("~ "): - active_title_change.emit(lines[i].replace("~ ", "")) - return - - active_title_change.emit("") - - -# Move the caret line to match a given title -func go_to_title(title: String) -> void: - var lines = text.split("\n") - for i in range(0, lines.size()): - if lines[i].strip_edges() == "~ " + title: - set_caret_line(i) - center_viewport_to_caret() - - -func get_character_names(beginning_with: String) -> PackedStringArray: - var names: PackedStringArray = [] - var lines = text.split("\n") - for line in lines: - if ": " in line: - var name: String = WEIGHTED_RANDOM_PREFIX.sub(line.split(": ")[0].strip_edges(), "") - if not name in names and matches_prompt(beginning_with, name): - names.append(name) - return names - - -# Mark a line as an error or not -func mark_line_as_error(line_number: int, is_error: bool) -> void: - if is_error: - set_line_background_color(line_number, theme_overrides.error_line_color) - set_line_gutter_icon(line_number, 0, get_theme_icon("StatusError", "EditorIcons")) - else: - set_line_background_color(line_number, theme_overrides.background_color) - set_line_gutter_icon(line_number, 0, null) - - -# Insert or wrap some bbcode at the caret/selection -func insert_bbcode(open_tag: String, close_tag: String = "") -> void: - if close_tag == "": - insert_text_at_caret(open_tag) - grab_focus() - else: - var selected_text = get_selected_text() - insert_text_at_caret("%s%s%s" % [open_tag, selected_text, close_tag]) - grab_focus() - set_caret_column(get_caret_column() - close_tag.length()) - -# Insert text at current caret position -# Move Caret down 1 line if not => END -func insert_text(text: String) -> void: - if text != "=> END": - insert_text_at_caret(text+"\n") - set_caret_line(get_caret_line()+1) - else: - insert_text_at_caret(text) - grab_focus() - - -# Toggle the selected lines as comments -func toggle_comment() -> void: - begin_complex_operation() - - var comment_delimiter: String = delimiter_comments[0] - var is_first_line: bool = true - var will_comment: bool = true - var selections: Array = [] - var line_offsets: Dictionary = {} - - for caret_index in range(0, get_caret_count()): - var from_line: int = get_caret_line(caret_index) - var from_column: int = get_caret_column(caret_index) - var to_line: int = get_caret_line(caret_index) - var to_column: int = get_caret_column(caret_index) - - if has_selection(caret_index): - from_line = get_selection_from_line(caret_index) - to_line = get_selection_to_line(caret_index) - from_column = get_selection_from_column(caret_index) - to_column = get_selection_to_column(caret_index) - - selections.append({ - from_line = from_line, - from_column = from_column, - to_line = to_line, - to_column = to_column - }) - - for line_number in range(from_line, to_line + 1): - if line_offsets.has(line_number): continue - - var line_text: String = get_line(line_number) - - # The first line determines if we are commenting or uncommentingg - if is_first_line: - is_first_line = false - will_comment = not line_text.strip_edges().begins_with(comment_delimiter) - - # Only comment/uncomment if the current line needs to - if will_comment: - set_line(line_number, comment_delimiter + line_text) - line_offsets[line_number] = 1 - elif line_text.begins_with(comment_delimiter): - set_line(line_number, line_text.substr(comment_delimiter.length())) - line_offsets[line_number] = -1 - else: - line_offsets[line_number] = 0 - - for caret_index in range(0, get_caret_count()): - var selection: Dictionary = selections[caret_index] - select( - selection.from_line, - selection.from_column + line_offsets[selection.from_line], - selection.to_line, - selection.to_column + line_offsets[selection.to_line], - caret_index - ) - set_caret_column(selection.from_column + line_offsets[selection.from_line], false, caret_index) - - end_complex_operation() - - text_set.emit() - text_changed.emit() - - -# Move the selected lines up or down -func move_line(offset: int) -> void: - offset = clamp(offset, -1, 1) - - var cursor = get_cursor() - var reselect: bool = false - var from: int = cursor.y - var to: int = cursor.y - if has_selection(): - reselect = true - from = get_selection_from_line() - to = get_selection_to_line() - - var lines := text.split("\n") - - # We can't move the lines out of bounds - if from + offset < 0 or to + offset >= lines.size(): return - - var target_from_index = from - 1 if offset == -1 else to + 1 - var target_to_index = to if offset == -1 else from - var line_to_move = lines[target_from_index] - lines.remove_at(target_from_index) - lines.insert(target_to_index, line_to_move) - - text = "\n".join(lines) - - cursor.y += offset - from += offset - to += offset - if reselect: - select(from, 0, to, get_line_width(to)) - set_cursor(cursor) - text_changed.emit() - - -### Signals - - -func _on_code_edit_symbol_validate(symbol: String) -> void: - if symbol.begins_with("res://") and symbol.ends_with(".dialogue"): - set_symbol_lookup_word_as_valid(true) - return - - for title in get_titles(): - if symbol == title: - set_symbol_lookup_word_as_valid(true) - return - set_symbol_lookup_word_as_valid(false) - - -func _on_code_edit_symbol_lookup(symbol: String, line: int, column: int) -> void: - if symbol.begins_with("res://") and symbol.ends_with(".dialogue"): - external_file_requested.emit(symbol, "") - else: - go_to_title(symbol) - - -func _on_code_edit_text_changed() -> void: - request_code_completion(true) - - -func _on_code_edit_text_set() -> void: - queue_redraw() - - -func _on_code_edit_caret_changed() -> void: - check_active_title() - last_selected_text = get_selected_text() - - -func _on_code_edit_gutter_clicked(line: int, gutter: int) -> void: - var line_errors = errors.filter(func(error): return error.line_number == line) - if line_errors.size() > 0: - error_clicked.emit(line) diff --git a/addons/dialogue_manager/components/code_edit.tscn b/addons/dialogue_manager/components/code_edit.tscn deleted file mode 100644 index a974ea3..0000000 --- a/addons/dialogue_manager/components/code_edit.tscn +++ /dev/null @@ -1,56 +0,0 @@ -[gd_scene load_steps=4 format=3 uid="uid://civ6shmka5e8u"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit_syntax_highlighter.gd" id="1_58cfo"] -[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit.gd" id="1_g324i"] - -[sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_cobxx"] -script = ExtResource("1_58cfo") - -[node name="CodeEdit" type="CodeEdit"] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -text = "~ title_thing - -if this = \"that\" or 'this' -Nathan: Something -- Then [if test.thing() == 2.0] => somewhere -- Other => END! - -~ somewhere - -set has_something = true -=> END" -highlight_all_occurrences = true -highlight_current_line = true -draw_tabs = true -syntax_highlighter = SubResource("SyntaxHighlighter_cobxx") -scroll_past_end_of_file = true -minimap_draw = true -symbol_lookup_on_click = true -line_folding = true -gutters_draw_line_numbers = true -gutters_draw_fold_gutter = true -delimiter_strings = Array[String](["\" \""]) -delimiter_comments = Array[String](["#"]) -code_completion_enabled = true -code_completion_prefixes = Array[String]([">", "<"]) -indent_automatic = true -auto_brace_completion_enabled = true -auto_brace_completion_highlight_matching = true -auto_brace_completion_pairs = { -"\"": "\"", -"(": ")", -"[": "]", -"{": "}" -} -script = ExtResource("1_g324i") - -[connection signal="caret_changed" from="." to="." method="_on_code_edit_caret_changed"] -[connection signal="gutter_clicked" from="." to="." method="_on_code_edit_gutter_clicked"] -[connection signal="symbol_lookup" from="." to="." method="_on_code_edit_symbol_lookup"] -[connection signal="symbol_validate" from="." to="." method="_on_code_edit_symbol_validate"] -[connection signal="text_changed" from="." to="." method="_on_code_edit_text_changed"] -[connection signal="text_set" from="." to="." method="_on_code_edit_text_set"] diff --git a/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd b/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd deleted file mode 100644 index fe1b8bd..0000000 --- a/addons/dialogue_manager/components/code_edit_syntax_highlighter.gd +++ /dev/null @@ -1,382 +0,0 @@ -@tool -extends SyntaxHighlighter - - -enum ExpressionType {DO, SET, IF} - - -var dialogue_manager_parser: DialogueManagerParser = DialogueManagerParser.new() - -var regex_titles: RegEx = RegEx.create_from_string("^\\s*(?<title>~\\s+[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+)") -var regex_comments: RegEx = RegEx.create_from_string("(?:(?>\"(?:\\\\\"|[^\"\\n])*\")[^\"\\n]*?\\s*(?<comment>#[^\\n]*)$|^[^\"#\\n]*?\\s*(?<comment2>#[^\\n]*))") -var regex_mutation: RegEx = RegEx.create_from_string("^\\s*(do|do!|set) (?<mutation>.*)") -var regex_condition: RegEx = RegEx.create_from_string("^\\s*(if|elif|while|else if) (?<condition>.*)") -var regex_wcondition: RegEx = RegEx.create_from_string("\\[if (?<condition>((?:[^\\[\\]]*)|(?:\\[(?1)\\]))*?)\\]") -var regex_wendif: RegEx = RegEx.create_from_string("\\[(\\/if|else)\\]") -var regex_rgroup: RegEx = RegEx.create_from_string("\\[\\[(?<options>.*?)\\]\\]") -var regex_endconditions: RegEx = RegEx.create_from_string("^\\s*(endif|else):?\\s*$") -var regex_tags: RegEx = RegEx.create_from_string("\\[(?<tag>(?!(?:ID:.*)|if)[a-zA-Z_][a-zA-Z0-9_]*!?)(?:[= ](?<val>[^\\[\\]]+))?\\](?:(?<text>(?!\\[\\/\\k<tag>\\]).*?)?(?<end>\\[\\/\\k<tag>\\]))?") -var regex_dialogue: RegEx = RegEx.create_from_string("^\\s*(?:(?<random>\\%[\\d.]* )|(?<response>- ))?(?:(?<character>[^#:]*): )?(?<dialogue>.*)$") -var regex_goto: RegEx = RegEx.create_from_string("=><? (?:(?<file>[^\\/]+)\\/)?(?<title>[^\\/]*)") -var regex_string: RegEx = RegEx.create_from_string("^(?<delimiter>[\"'])(?<content>(?:\\\\{2})*|(?:.*?[^\\\\](?:\\\\{2})*))\\1$") -var regex_escape: RegEx = RegEx.create_from_string("\\\\.") -var regex_number: RegEx = RegEx.create_from_string("^-?(?:(?:0x(?:[0-9A-Fa-f]{2})+)|(?:0b[01]+)|(?:\\d+(?:(?:[\\.]\\d*)?(?:e\\d+)?)|(?:_\\d+)+)?)$") -var regex_array: RegEx = RegEx.create_from_string("\\[((?>[^\\[\\]]+|(?R))*)\\]") -var regex_dict: RegEx = RegEx.create_from_string("^\\{((?>[^\\{\\}]+|(?R))*)\\}$") -var regex_kvdict: RegEx = RegEx.create_from_string("^\\s*(?<left>.*?)\\s*(?<colon>:|=)\\s*(?<right>[^\\/]+)$") -var regex_commas: RegEx = RegEx.create_from_string("([^,]+)(?:\\s*,\\s*)?") -var regex_assignment: RegEx = RegEx.create_from_string("^\\s*(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*(?<op>(?:\\/|\\*|-|\\+)?=)\\s*(?<val>.*)$") -var regex_varname: RegEx = RegEx.create_from_string("^\\s*(?!true|false|and|or|not|in|null)(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*$") -var regex_keyword: RegEx = RegEx.create_from_string("^\\s*(true|false|null)\\s*$") -var regex_function: RegEx = RegEx.create_from_string("^\\s*([a-zA-Z_][a-zA-Z_0-9]*\\s*)\\(") -var regex_comparison: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s*(?<op>==|>=|<=|<|>|!=)\\s*(?<right>.*)$") -var regex_blogical: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s+(?<op>and|or|in)\\s+(?<right>.*)$") -var regex_ulogical: RegEx = RegEx.create_from_string("^\\s*(?<op>not)\\s+(?<right>.*)$") -var regex_paren: RegEx = RegEx.create_from_string("\\((?<paren>((?:[^\\(\\)]*)|(?:\\((?1)\\)))*?)\\)") - -var cache: Dictionary = {} - - -func _notification(what: int) -> void: - if what == NOTIFICATION_PREDELETE: - dialogue_manager_parser.free() - - -func _clear_highlighting_cache() -> void: - cache = {} - - -## Returns the syntax coloring for a dialogue file line -func _get_line_syntax_highlighting(line: int) -> Dictionary: - var colors: Dictionary = {} - var text_edit: TextEdit = get_text_edit() - var text: String = text_edit.get_line(line) - - # Prevents an error from popping up while developing - if not is_instance_valid(text_edit) or text_edit.theme_overrides.is_empty(): - return colors - - # Disable this, as well as the line at the bottom of this function to remove the cache. - if text in cache: - return cache[text] - - # Comments, we have to remove them at this point so the rest of the processing is easier - # Counts both end-of-line and single-line comments - # Comments are not allowed within dialogue lines or response lines, so we ask the parser what it thinks the current line is - if not (dialogue_manager_parser.is_dialogue_line(text) or dialogue_manager_parser.is_response_line(text)) or dialogue_manager_parser.is_line_empty(text) or dialogue_manager_parser.is_import_line(text): - var comment_matches: Array[RegExMatch] = regex_comments.search_all(text) - for comment_match in comment_matches: - for i in ["comment", "comment2"]: - if i in comment_match.names: - colors[comment_match.get_start(i)] = {"color": text_edit.theme_overrides.comments_color} - text = text.substr(0, comment_match.get_start(i)) - - # Dialogues. - var dialogue_matches: Array[RegExMatch] = regex_dialogue.search_all(text) - for dialogue_match in dialogue_matches: - if "random" in dialogue_match.names: - colors[dialogue_match.get_start("random")] = {"color": text_edit.theme_overrides.symbols_color} - colors[dialogue_match.get_end("random")] = {"color": text_edit.theme_overrides.text_color} - if "response" in dialogue_match.names: - colors[dialogue_match.get_start("response")] = {"color": text_edit.theme_overrides.symbols_color} - colors[dialogue_match.get_end("response")] = {"color": text_edit.theme_overrides.text_color} - if "character" in dialogue_match.names: - colors[dialogue_match.get_start("character")] = {"color": text_edit.theme_overrides.members_color} - colors[dialogue_match.get_end("character")] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_dialogue_syntax_highlighting(dialogue_match.get_start("dialogue"), dialogue_match.get_string("dialogue")), true) - - # Title lines. - if dialogue_manager_parser.is_title_line(text): - var title_matches: Array[RegExMatch] = regex_titles.search_all(text) - for title_match in title_matches: - colors[title_match.get_start("title")] = {"color": text_edit.theme_overrides.titles_color} - - # Import lines. - var import_matches: Array[RegExMatch] = dialogue_manager_parser.IMPORT_REGEX.search_all(text) - for import_match in import_matches: - colors[import_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} - colors[import_match.get_start("path") - 1] = {"color": text_edit.theme_overrides.strings_color} - colors[import_match.get_end("path") + 1] = {"color": text_edit.theme_overrides.conditions_color} - colors[import_match.get_start("prefix")] = {"color": text_edit.theme_overrides.members_color} - colors[import_match.get_end("prefix")] = {"color": text_edit.theme_overrides.conditions_color} - - # Using clauses - var using_matches: Array[RegExMatch] = dialogue_manager_parser.USING_REGEX.search_all(text) - for using_match in using_matches: - colors[using_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} - colors[using_match.get_start("state") - 1] = {"color": text_edit.theme_overrides.text_color} - - # Condition keywords and expressions. - var condition_matches: Array[RegExMatch] = regex_condition.search_all(text) - for condition_match in condition_matches: - colors[condition_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} - colors[condition_match.get_end(1)] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_expression_syntax_highlighting(condition_match.get_start("condition"), ExpressionType.IF, condition_match.get_string("condition")), true) - # endif/else - var endcondition_matches: Array[RegExMatch] = regex_endconditions.search_all(text) - for endcondition_match in endcondition_matches: - colors[endcondition_match.get_start(1)] = {"color": text_edit.theme_overrides.conditions_color} - colors[endcondition_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - - # Mutations. - var mutation_matches: Array[RegExMatch] = regex_mutation.search_all(text) - for mutation_match in mutation_matches: - colors[mutation_match.get_start(0)] = {"color": text_edit.theme_overrides.mutations_color} - colors.merge(_get_expression_syntax_highlighting(mutation_match.get_start("mutation"), ExpressionType.DO if mutation_match.strings[1] == "do" else ExpressionType.SET, mutation_match.get_string("mutation")), true) - - # CodeEdit seems to have issues if the Dictionary keys weren't added in order? - var new_colors: Dictionary = {} - var ordered_keys: Array = colors.keys() - ordered_keys.sort() - for index in ordered_keys: - new_colors[index] = colors[index] - - cache[text] = new_colors - return new_colors - - -## Returns the syntax highlighting for a dialogue line -func _get_dialogue_syntax_highlighting(start_index: int, text: String) -> Dictionary: - var text_edit: TextEdit = get_text_edit() - var colors: Dictionary = {} - - # #tag style tags - var hashtag_matches: Array[RegExMatch] = dialogue_manager_parser.TAGS_REGEX.search_all(text) - for hashtag_match in hashtag_matches: - colors[start_index + hashtag_match.get_start(0)] = { "color": text_edit.theme_overrides.comments_color } - colors[start_index + hashtag_match.get_end(0)] = { "color": text_edit.theme_overrides.text_color } - - # Global tags, like bbcode. - var tag_matches: Array[RegExMatch] = regex_tags.search_all(text) - for tag_match in tag_matches: - colors[start_index + tag_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - if "val" in tag_match.names: - colors.merge(_get_literal_syntax_highlighting(start_index + tag_match.get_start("val"), tag_match.get_string("val")), true) - colors[start_index + tag_match.get_end("val")] = {"color": text_edit.theme_overrides.symbols_color} - # Showing the text color straight in the editor for better ease-of-use - if tag_match.get_string("tag") == "color": - colors[start_index + tag_match.get_start("val")] = {"color": Color.from_string(tag_match.get_string("val"), text_edit.theme_overrides.text_color)} - if "text" in tag_match.names: - colors[start_index + tag_match.get_start("text")] = {"color": text_edit.theme_overrides.text_color} - # Text can still contain tags if several effects are applied ([center][b]Something[/b][/center], so recursing - colors.merge(_get_dialogue_syntax_highlighting(start_index + tag_match.get_start("text"), tag_match.get_string("text")), true) - colors[start_index + tag_match.get_end("text")] = {"color": text_edit.theme_overrides.symbols_color} - if "end" in tag_match.names: - colors[start_index + tag_match.get_start("end")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + tag_match.get_end("end")] = {"color": text_edit.theme_overrides.text_color} - colors[start_index + tag_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - # ID tag. - var translation_matches: Array[RegExMatch] = dialogue_manager_parser.TRANSLATION_REGEX.search_all(text) - for translation_match in translation_matches: - colors[start_index + translation_match.get_start(0)] = {"color": text_edit.theme_overrides.comments_color} - colors[start_index + translation_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - # Replacements. - var replacement_matches: Array[RegExMatch] = dialogue_manager_parser.REPLACEMENTS_REGEX.search_all(text) - for replacement_match in replacement_matches: - colors[start_index + replacement_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + replacement_match.get_start(1)] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + replacement_match.get_start(1), replacement_match.strings[1]), true) - colors[start_index + replacement_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + replacement_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - # Jump at the end of a response. - var goto_matches: Array[RegExMatch] = regex_goto.search_all(text) - for goto_match in goto_matches: - colors[start_index + goto_match.get_start(0)] = {"color": text_edit.theme_overrides.jumps_color} - if "file" in goto_match.names: - colors[start_index + goto_match.get_start("file")] = {"color": text_edit.theme_overrides.members_color} - colors[start_index + goto_match.get_end("file")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + goto_match.get_start("title")] = {"color": text_edit.theme_overrides.titles_color} - colors[start_index + goto_match.get_end("title")] = {"color": text_edit.theme_overrides.jumps_color} - colors[start_index + goto_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - # Wrapped condition. - var wcondition_matches: Array[RegExMatch] = regex_wcondition.search_all(text) - for wcondition_match in wcondition_matches: - colors[start_index + wcondition_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + wcondition_match.get_start(0) + 1] = {"color": text_edit.theme_overrides.conditions_color} - colors[start_index + wcondition_match.get_start(0) + 3] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + wcondition_match.get_start("condition"), wcondition_match.get_string("condition")), true) - colors[start_index + wcondition_match.get_end("condition")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + wcondition_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - # [/if] tag for color matching with the opening tag - var wendif_matches: Array[RegExMatch] = regex_wendif.search_all(text) - for wendif_match in wendif_matches: - colors[start_index + wendif_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + wendif_match.get_start(1)] = {"color": text_edit.theme_overrides.conditions_color} - colors[start_index + wendif_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + wendif_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - # Random groups - var rgroup_matches: Array[RegExMatch] = regex_rgroup.search_all(text) - for rgroup_match in rgroup_matches: - colors[start_index + rgroup_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + rgroup_match.get_start("options")] = {"color": text_edit.theme_overrides.text_color} - var separator_matches: Array[RegExMatch] = RegEx.create_from_string("\\|").search_all(rgroup_match.get_string("options")) - for separator_match in separator_matches: - colors[start_index + rgroup_match.get_start("options") + separator_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + rgroup_match.get_start("options") + separator_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - colors[start_index + rgroup_match.get_end("options")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + rgroup_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color} - - return colors - - -## Returns the syntax highlighting for an expression (mutation set/do, or condition) -func _get_expression_syntax_highlighting(start_index: int, type: ExpressionType, text: String) -> Dictionary: - var text_edit: TextEdit = get_text_edit() - var colors: Dictionary = {} - - if type == ExpressionType.SET: - var assignment_matches: Array[RegExMatch] = regex_assignment.search_all(text) - for assignment_match in assignment_matches: - colors[start_index + assignment_match.get_start("var")] = {"color": text_edit.theme_overrides.text_color} - if "attr" in assignment_match.names: - colors[start_index + assignment_match.get_start("attr")] = {"color": text_edit.theme_overrides.members_color} - colors[start_index + assignment_match.get_end("attr")] = {"color": text_edit.theme_overrides.text_color} - if "key" in assignment_match.names: - # Braces are outside of the key, so coloring them symbols_color - colors[start_index + assignment_match.get_start("key") - 1] = {"color": text_edit.theme_overrides.symbols_color} - colors.merge(_get_literal_syntax_highlighting(start_index + assignment_match.get_start("key"), assignment_match.get_string("key")), true) - colors[start_index + assignment_match.get_end("key")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + assignment_match.get_end("key") + 1] = {"color": text_edit.theme_overrides.text_color} - - colors[start_index + assignment_match.get_start("op")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + assignment_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + assignment_match.get_start("val"), assignment_match.get_string("val")), true) - else: - colors.merge(_get_literal_syntax_highlighting(start_index, text), true) - - return colors - - -## Returns the syntax highlighting for a literal. -## For this purpose, "literal" refers to a regular code line that could be used to get a value out of: -## - function calls -## - real literals (bool, string, int, float, etc.) -## - logical operators (>, <, >=, or, and, not, etc.) -func _get_literal_syntax_highlighting(start_index: int, text: String) -> Dictionary: - var text_edit: TextEdit = get_text_edit() - var colors: Dictionary = {} - - # Removing spaces at start/end of the literal - var text_length: int = text.length() - text = text.lstrip(" ") - start_index += text_length - text.length() - text = text.rstrip(" ") - - # Parenthesis expression. - var paren_matches: Array[RegExMatch] = regex_paren.search_all(text) - for paren_match in paren_matches: - colors[start_index + paren_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + paren_match.get_start(0) + 1] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + paren_match.get_start("paren"), paren_match.get_string("paren")), true) - colors[start_index + paren_match.get_end(0) - 1] = {"color": text_edit.theme_overrides.symbols_color} - - # Strings. - var string_matches: Array[RegExMatch] = regex_string.search_all(text) - for string_match in string_matches: - colors[start_index + string_match.get_start(0)] = {"color": text_edit.theme_overrides.strings_color} - if "content" in string_match.names: - var escape_matches: Array[RegExMatch] = regex_escape.search_all(string_match.get_string("content")) - for escape_match in escape_matches: - colors[start_index + string_match.get_start("content") + escape_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + string_match.get_start("content") + escape_match.get_end(0)] = {"color": text_edit.theme_overrides.strings_color} - - # Numbers. - var number_matches: Array[RegExMatch] = regex_number.search_all(text) - for number_match in number_matches: - colors[start_index + number_match.get_start(0)] = {"color": text_edit.theme_overrides.numbers_color} - - # Arrays. - var array_matches: Array[RegExMatch] = regex_array.search_all(text) - for array_match in array_matches: - colors[start_index + array_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors.merge(_get_list_syntax_highlighting(start_index + array_match.get_start(1), array_match.strings[1]), true) - colors[start_index + array_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - - # Dictionaries. - var dict_matches: Array[RegExMatch] = regex_dict.search_all(text) - for dict_match in dict_matches: - colors[start_index + dict_match.get_start(0)] = {"color": text_edit.theme_overrides.symbols_color} - colors.merge(_get_list_syntax_highlighting(start_index + dict_match.get_start(1), dict_match.strings[1]), true) - colors[start_index + dict_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - - # Dictionary key: value pairs - var kvdict_matches: Array[RegExMatch] = regex_kvdict.search_all(text) - for kvdict_match in kvdict_matches: - colors.merge(_get_literal_syntax_highlighting(start_index + kvdict_match.get_start("left"), kvdict_match.get_string("left")), true) - colors[start_index + kvdict_match.get_start("colon")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + kvdict_match.get_end("colon")] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + kvdict_match.get_start("right"), kvdict_match.get_string("right")), true) - - # Booleans. - var bool_matches: Array[RegExMatch] = regex_keyword.search_all(text) - for bool_match in bool_matches: - colors[start_index + bool_match.get_start(0)] = {"color": text_edit.theme_overrides.conditions_color} - - # Functions. - var function_matches: Array[RegExMatch] = regex_function.search_all(text) - for function_match in function_matches: - var last_brace_index: int = text.rfind(")") - colors[start_index + function_match.get_start(1)] = {"color": text_edit.theme_overrides.mutations_color} - colors[start_index + function_match.get_end(1)] = {"color": text_edit.theme_overrides.symbols_color} - colors.merge(_get_list_syntax_highlighting(start_index + function_match.get_end(0), text.substr(function_match.get_end(0), last_brace_index - function_match.get_end(0))), true) - colors[start_index + last_brace_index] = {"color": text_edit.theme_overrides.symbols_color} - - # Variables. - var varname_matches: Array[RegExMatch] = regex_varname.search_all(text) - for varname_match in varname_matches: - colors[start_index + varname_match.get_start("var")] = {"color": text_edit.theme_overrides.text_color} - if "attr" in varname_match.names: - colors[start_index + varname_match.get_start("attr")] = {"color": text_edit.theme_overrides.members_color} - colors[start_index + varname_match.get_end("attr")] = {"color": text_edit.theme_overrides.text_color} - if "key" in varname_match.names: - # Braces are outside of the key, so coloring them symbols_color - colors[start_index + varname_match.get_start("key") - 1] = {"color": text_edit.theme_overrides.symbols_color} - colors.merge(_get_literal_syntax_highlighting(start_index + varname_match.get_start("key"), varname_match.get_string("key")), true) - colors[start_index + varname_match.get_end("key")] = {"color": text_edit.theme_overrides.symbols_color} - - # Comparison operators. - var comparison_matches: Array[RegExMatch] = regex_comparison.search_all(text) - for comparison_match in comparison_matches: - colors.merge(_get_literal_syntax_highlighting(start_index + comparison_match.get_start("left"), comparison_match.get_string("left")), true) - colors[start_index + comparison_match.get_start("op")] = {"color": text_edit.theme_overrides.symbols_color} - colors[start_index + comparison_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} - var right = comparison_match.get_string("right") - if right.ends_with(":"): - right = right.substr(0, right.length() - 1) - colors.merge(_get_literal_syntax_highlighting(start_index + comparison_match.get_start("right"), right), true) - colors[start_index + comparison_match.get_start("right") + right.length()] = { "color": text_edit.theme_overrides.symbols_color } - - # Logical binary operators. - var blogical_matches: Array[RegExMatch] = regex_blogical.search_all(text) - for blogical_match in blogical_matches: - colors.merge(_get_literal_syntax_highlighting(start_index + blogical_match.get_start("left"), blogical_match.get_string("left")), true) - colors[start_index + blogical_match.get_start("op")] = {"color": text_edit.theme_overrides.conditions_color} - colors[start_index + blogical_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + blogical_match.get_start("right"), blogical_match.get_string("right")), true) - - # Logical unary operators. - var ulogical_matches: Array[RegExMatch] = regex_ulogical.search_all(text) - for ulogical_match in ulogical_matches: - colors[start_index + ulogical_match.get_start("op")] = {"color": text_edit.theme_overrides.conditions_color} - colors[start_index + ulogical_match.get_end("op")] = {"color": text_edit.theme_overrides.text_color} - colors.merge(_get_literal_syntax_highlighting(start_index + ulogical_match.get_start("right"), ulogical_match.get_string("right")), true) - - return colors - - -## Returns the syntax coloring for a list of literals separated by commas -func _get_list_syntax_highlighting(start_index: int, text: String) -> Dictionary: - var text_edit: TextEdit = get_text_edit() - var colors: Dictionary = {} - - # Comma-separated list of literals (for arrays and function arguments) - var element_matches: Array[RegExMatch] = regex_commas.search_all(text) - for element_match in element_matches: - colors.merge(_get_literal_syntax_highlighting(start_index + element_match.get_start(1), element_match.strings[1]), true) - - return colors diff --git a/addons/dialogue_manager/components/dialogue_cache.gd b/addons/dialogue_manager/components/dialogue_cache.gd deleted file mode 100644 index 5304d4b..0000000 --- a/addons/dialogue_manager/components/dialogue_cache.gd +++ /dev/null @@ -1,160 +0,0 @@ -extends Node - - -const DialogueConstants = preload("../constants.gd") -const DialogueSettings = preload("../settings.gd") -const DialogueManagerParseResult = preload("./parse_result.gd") - - -# Keeps track of errors and dependencies. -# { -# <dialogue file path> = { -# path = <dialogue file path>, -# dependencies = [<dialogue file path>, <dialogue file path>], -# errors = [<error>, <error>] -# } -# } -var _cache: Dictionary = {} - -var _update_dependency_timer: Timer = Timer.new() -var _update_dependency_paths: PackedStringArray = [] - - -func _ready() -> void: - add_child(_update_dependency_timer) - _update_dependency_timer.timeout.connect(_on_update_dependency_timeout) - - _build_cache() - - -func reimport_files(files: PackedStringArray = []) -> void: - if files.is_empty(): files = get_files() - - var file_system: EditorFileSystem = Engine.get_meta("DialogueManagerPlugin") \ - .get_editor_interface() \ - .get_resource_filesystem() - - # NOTE: Godot 4.2rc1 has an issue with reimporting more than one - # file at a time so we do them one by one - for file in files: - file_system.reimport_files([file]) - await get_tree().create_timer(0.2) - - -## Add a dialogue file to the cache. -func add_file(path: String, parse_results: DialogueManagerParseResult = null) -> void: - _cache[path] = { - path = path, - dependencies = [], - errors = [] - } - - if parse_results != null: - _cache[path].dependencies = Array(parse_results.imported_paths).filter(func(d): return d != path) - _cache[path].parsed_at = Time.get_ticks_msec() - - # If this is a fresh cache entry then we need to check for dependencies - if parse_results == null and not _update_dependency_paths.has(path): - queue_updating_dependencies(path) - - -## Get the file paths in the cache. -func get_files() -> PackedStringArray: - return _cache.keys() - - -## Remember any errors in a dialogue file. -func add_errors_to_file(path: String, errors: Array[Dictionary]) -> void: - if _cache.has(path): - _cache[path].errors = errors - else: - _cache[path] = { - path = path, - resource_path = "", - dependencies = [], - errors = errors - } - - -## Get a list of files that have errors in them. -func get_files_with_errors() -> Array[Dictionary]: - var files_with_errors: Array[Dictionary] = [] - for dialogue_file in _cache.values(): - if dialogue_file and dialogue_file.errors.size() > 0: - files_with_errors.append(dialogue_file) - return files_with_errors - - -## Queue a file to have it's dependencies checked -func queue_updating_dependencies(of_path: String) -> void: - _update_dependency_timer.stop() - if not _update_dependency_paths.has(of_path): - _update_dependency_paths.append(of_path) - _update_dependency_timer.start(0.5) - - -## Update any references to a file path that has moved -func move_file_path(from_path: String, to_path: String) -> void: - if not _cache.has(from_path): return - - if to_path != "": - _cache[to_path] = _cache[from_path].duplicate() - _cache.erase(from_path) - - -## Get any dialogue files that import a given path. -func get_files_with_dependency(imported_path: String) -> Array: - return _cache.values().filter(func(d): return d.dependencies.has(imported_path)) - - -## Get any paths that are dependent on a given path -func get_dependent_paths_for_reimport(on_path: String) -> PackedStringArray: - return get_files_with_dependency(on_path) \ - .filter(func(d): return Time.get_ticks_msec() - d.get("parsed_at", 0) > 3000) \ - .map(func(d): return d.path) - - -# Build the initial cache for dialogue files. -func _build_cache() -> void: - var current_files: PackedStringArray = _get_dialogue_files_in_filesystem() - for file in current_files: - add_file(file) - - -# Recursively find any dialogue files in a directory -func _get_dialogue_files_in_filesystem(path: String = "res://") -> PackedStringArray: - var files: PackedStringArray = [] - - if DirAccess.dir_exists_absolute(path): - var dir = DirAccess.open(path) - dir.list_dir_begin() - var file_name = dir.get_next() - while file_name != "": - var file_path: String = (path + "/" + file_name).simplify_path() - if dir.current_is_dir(): - if not file_name in [".godot", ".tmp"]: - files.append_array(_get_dialogue_files_in_filesystem(file_path)) - elif file_name.get_extension() == "dialogue": - files.append(file_path) - file_name = dir.get_next() - - return files - - -### Signals - - -func _on_update_dependency_timeout() -> void: - _update_dependency_timer.stop() - var import_regex: RegEx = RegEx.create_from_string("import \"(?<path>.*?)\"") - var file: FileAccess - var found_imports: Array[RegExMatch] - for path in _update_dependency_paths: - # Open the file and check for any "import" lines - file = FileAccess.open(path, FileAccess.READ) - found_imports = import_regex.search_all(file.get_as_text()) - var dependencies: PackedStringArray = [] - for found in found_imports: - dependencies.append(found.strings[found.names.path]) - _cache[path].dependencies = dependencies - _update_dependency_paths.clear() diff --git a/addons/dialogue_manager/components/download_update_panel.gd b/addons/dialogue_manager/components/download_update_panel.gd deleted file mode 100644 index 617d308..0000000 --- a/addons/dialogue_manager/components/download_update_panel.gd +++ /dev/null @@ -1,84 +0,0 @@ -@tool -extends Control - - -signal failed() -signal updated(updated_to_version: String) - - -const DialogueConstants = preload("../constants.gd") - -const TEMP_FILE_NAME = "user://temp.zip" - - -@onready var logo: TextureRect = %Logo -@onready var label: Label = $VBox/Label -@onready var http_request: HTTPRequest = $HTTPRequest -@onready var download_button: Button = %DownloadButton - -var next_version_release: Dictionary: - set(value): - next_version_release = value - label.text = DialogueConstants.translate(&"update.is_available_for_download") % value.tag_name.substr(1) - get: - return next_version_release - - -func _ready() -> void: - $VBox/Center/DownloadButton.text = DialogueConstants.translate(&"update.download_update") - $VBox/Center2/NotesButton.text = DialogueConstants.translate(&"update.release_notes") - - -### Signals - - -func _on_download_button_pressed() -> void: - # Safeguard the actual dialogue manager repo from accidentally updating itself - if FileAccess.file_exists("res://examples/test_scenes/test_scene.gd"): - prints("You can't update the addon from within itself.") - failed.emit() - return - - http_request.request(next_version_release.zipball_url) - download_button.disabled = true - download_button.text = DialogueConstants.translate(&"update.downloading") - - -func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void: - if result != HTTPRequest.RESULT_SUCCESS: - failed.emit() - return - - # Save the downloaded zip - var zip_file: FileAccess = FileAccess.open(TEMP_FILE_NAME, FileAccess.WRITE) - zip_file.store_buffer(body) - zip_file.close() - - OS.move_to_trash(ProjectSettings.globalize_path("res://addons/dialogue_manager")) - - var zip_reader: ZIPReader = ZIPReader.new() - zip_reader.open(TEMP_FILE_NAME) - var files: PackedStringArray = zip_reader.get_files() - - var base_path = files[1] - # Remove archive folder - files.remove_at(0) - # Remove assets folder - files.remove_at(0) - - for path in files: - var new_file_path: String = path.replace(base_path, "") - if path.ends_with("/"): - DirAccess.make_dir_recursive_absolute("res://addons/%s" % new_file_path) - else: - var file: FileAccess = FileAccess.open("res://addons/%s" % new_file_path, FileAccess.WRITE) - file.store_buffer(zip_reader.read_file(path)) - - zip_reader.close() - DirAccess.remove_absolute(TEMP_FILE_NAME) - - updated.emit(next_version_release.tag_name.substr(1)) - - -func _on_notes_button_pressed() -> void: - OS.shell_open(next_version_release.html_url) diff --git a/addons/dialogue_manager/components/download_update_panel.tscn b/addons/dialogue_manager/components/download_update_panel.tscn deleted file mode 100644 index f3f4523..0000000 --- a/addons/dialogue_manager/components/download_update_panel.tscn +++ /dev/null @@ -1,60 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://qdxrxv3c3hxk"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/download_update_panel.gd" id="1_4tm1k"] -[ext_resource type="Texture2D" uid="uid://d3baj6rygkb3f" path="res://addons/dialogue_manager/assets/update.svg" id="2_4o2m6"] - -[node name="DownloadUpdatePanel" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("1_4tm1k") - -[node name="HTTPRequest" type="HTTPRequest" parent="."] - -[node name="VBox" type="VBoxContainer" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = -1.0 -offset_top = 9.0 -offset_right = -1.0 -offset_bottom = 9.0 -grow_horizontal = 2 -grow_vertical = 2 -theme_override_constants/separation = 10 - -[node name="Logo" type="TextureRect" parent="VBox"] -unique_name_in_owner = true -clip_contents = true -custom_minimum_size = Vector2(300, 80) -layout_mode = 2 -texture = ExtResource("2_4o2m6") -stretch_mode = 5 - -[node name="Label" type="Label" parent="VBox"] -layout_mode = 2 -text = "v1.2.3 is available for download." -horizontal_alignment = 1 - -[node name="Center" type="CenterContainer" parent="VBox"] -layout_mode = 2 - -[node name="DownloadButton" type="Button" parent="VBox/Center"] -unique_name_in_owner = true -layout_mode = 2 -text = "Download update" - -[node name="Center2" type="CenterContainer" parent="VBox"] -layout_mode = 2 - -[node name="NotesButton" type="LinkButton" parent="VBox/Center2"] -layout_mode = 2 -text = "Read release notes" - -[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_request_completed"] -[connection signal="pressed" from="VBox/Center/DownloadButton" to="." method="_on_download_button_pressed"] -[connection signal="pressed" from="VBox/Center2/NotesButton" to="." method="_on_notes_button_pressed"] diff --git a/addons/dialogue_manager/components/errors_panel.gd b/addons/dialogue_manager/components/errors_panel.gd deleted file mode 100644 index f3e294d..0000000 --- a/addons/dialogue_manager/components/errors_panel.gd +++ /dev/null @@ -1,85 +0,0 @@ -@tool -extends HBoxContainer - - -signal error_pressed(line_number) - - -const DialogueConstants = preload("../constants.gd") - - -@onready var error_button: Button = $ErrorButton -@onready var next_button: Button = $NextButton -@onready var count_label: Label = $CountLabel -@onready var previous_button: Button = $PreviousButton - -## The index of the current error being shown -var error_index: int = 0: - set(next_error_index): - error_index = wrap(next_error_index, 0, errors.size()) - show_error() - get: - return error_index - -## The list of all errors -var errors: Array = []: - set(next_errors): - errors = next_errors - self.error_index = 0 - get: - return errors - - -func _ready() -> void: - apply_theme() - hide() - - -## Set up colors and icons -func apply_theme() -> void: - error_button.add_theme_color_override("font_color", get_theme_color("error_color", "Editor")) - error_button.add_theme_color_override("font_hover_color", get_theme_color("error_color", "Editor")) - error_button.icon = get_theme_icon("StatusError", "EditorIcons") - previous_button.icon = get_theme_icon("ArrowLeft", "EditorIcons") - next_button.icon = get_theme_icon("ArrowRight", "EditorIcons") - - -## Move the error index to match a given line -func show_error_for_line_number(line_number: int) -> void: - for i in range(0, errors.size()): - if errors[i].line_number == line_number: - self.error_index = i - - -## Show the current error -func show_error() -> void: - if errors.size() == 0: - hide() - else: - show() - count_label.text = DialogueConstants.translate(&"n_of_n").format({ index = error_index + 1, total = errors.size() }) - var error = errors[error_index] - error_button.text = DialogueConstants.translate(&"errors.line_and_message").format({ line = error.line_number + 1, column = error.column_number, message = DialogueConstants.get_error_message(error.error) }) - if error.has("external_error"): - error_button.text += " " + DialogueConstants.get_error_message(error.external_error) - - -### Signals - - -func _on_errors_panel_theme_changed() -> void: - apply_theme() - - -func _on_error_button_pressed() -> void: - emit_signal("error_pressed", errors[error_index].line_number, errors[error_index].column_number) - - -func _on_previous_button_pressed() -> void: - self.error_index -= 1 - _on_error_button_pressed() - - -func _on_next_button_pressed() -> void: - self.error_index += 1 - _on_error_button_pressed() diff --git a/addons/dialogue_manager/components/errors_panel.tscn b/addons/dialogue_manager/components/errors_panel.tscn deleted file mode 100644 index 956552b..0000000 --- a/addons/dialogue_manager/components/errors_panel.tscn +++ /dev/null @@ -1,56 +0,0 @@ -[gd_scene load_steps=4 format=3 uid="uid://cs8pwrxr5vxix"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/errors_panel.gd" id="1_nfm3c"] - -[sub_resource type="Image" id="Image_wy5pj"] -data = { -"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), -"format": "RGBA8", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_s6fxl"] -image = SubResource("Image_wy5pj") - -[node name="ErrorsPanel" type="HBoxContainer"] -visible = false -offset_right = 1024.0 -offset_bottom = 600.0 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("1_nfm3c") -metadata/_edit_layout_mode = 1 - -[node name="ErrorButton" type="Button" parent="."] -layout_mode = 2 -size_flags_horizontal = 3 -theme_override_colors/font_color = Color(0, 0, 0, 1) -theme_override_colors/font_hover_color = Color(0, 0, 0, 1) -theme_override_constants/h_separation = 3 -icon = SubResource("ImageTexture_s6fxl") -flat = true -alignment = 0 -text_overrun_behavior = 4 - -[node name="Spacer" type="Control" parent="."] -custom_minimum_size = Vector2(40, 0) -layout_mode = 2 - -[node name="PreviousButton" type="Button" parent="."] -layout_mode = 2 -icon = SubResource("ImageTexture_s6fxl") -flat = true - -[node name="CountLabel" type="Label" parent="."] -layout_mode = 2 - -[node name="NextButton" type="Button" parent="."] -layout_mode = 2 -icon = SubResource("ImageTexture_s6fxl") -flat = true - -[connection signal="pressed" from="ErrorButton" to="." method="_on_error_button_pressed"] -[connection signal="pressed" from="PreviousButton" to="." method="_on_previous_button_pressed"] -[connection signal="pressed" from="NextButton" to="." method="_on_next_button_pressed"] diff --git a/addons/dialogue_manager/components/files_list.gd b/addons/dialogue_manager/components/files_list.gd deleted file mode 100644 index ac4793d..0000000 --- a/addons/dialogue_manager/components/files_list.gd +++ /dev/null @@ -1,144 +0,0 @@ -@tool -extends VBoxContainer - - -signal file_selected(file_path: String) -signal file_popup_menu_requested(at_position: Vector2) -signal file_double_clicked(file_path: String) -signal file_middle_clicked(file_path: String) - - -const DialogueConstants = preload("../constants.gd") - -const MODIFIED_SUFFIX = "(*)" - - -@export var icon: Texture2D - -@onready var filter_edit: LineEdit = $FilterEdit -@onready var list: ItemList = $List - -var file_map: Dictionary = {} - -var current_file_path: String = "" - -var files: PackedStringArray = []: - set(next_files): - files = next_files - files.sort() - update_file_map() - apply_filter() - get: - return files - -var unsaved_files: Array[String] = [] - -var filter: String: - set(next_filter): - filter = next_filter - apply_filter() - get: - return filter - - -func _ready() -> void: - apply_theme() - - filter_edit.placeholder_text = DialogueConstants.translate(&"files_list.filter") - - -func select_file(file: String) -> void: - list.deselect_all() - for i in range(0, list.get_item_count()): - var item_text = list.get_item_text(i).replace(MODIFIED_SUFFIX, "") - if item_text == get_nice_file(file, item_text.count("/") + 1): - list.select(i) - - -func mark_file_as_unsaved(file: String, is_unsaved: bool) -> void: - if not file in unsaved_files and is_unsaved: - unsaved_files.append(file) - elif file in unsaved_files and not is_unsaved: - unsaved_files.erase(file) - apply_filter() - - -func update_file_map() -> void: - file_map = {} - for file in files: - var nice_file: String = get_nice_file(file) - - # See if a value with just the file name is already in the map - for key in file_map.keys(): - if file_map[key] == nice_file: - var bit_count = nice_file.count("/") + 2 - - var existing_nice_file = get_nice_file(key, bit_count) - nice_file = get_nice_file(file, bit_count) - - while nice_file == existing_nice_file: - bit_count += 1 - existing_nice_file = get_nice_file(key, bit_count) - nice_file = get_nice_file(file, bit_count) - - file_map[key] = existing_nice_file - - file_map[file] = nice_file - - -func get_nice_file(file_path: String, path_bit_count: int = 1) -> String: - var bits = file_path.replace("res://", "").replace(".dialogue", "").split("/") - bits = bits.slice(-path_bit_count) - return "/".join(bits) - - -func apply_filter() -> void: - list.clear() - for file in file_map.keys(): - if filter == "" or filter.to_lower() in file.to_lower(): - var nice_file = file_map[file] - if file in unsaved_files: - nice_file += MODIFIED_SUFFIX - var new_id := list.add_item(nice_file) - list.set_item_icon(new_id, icon) - - select_file(current_file_path) - - -func apply_theme() -> void: - if is_instance_valid(filter_edit): - filter_edit.right_icon = get_theme_icon("Search", "EditorIcons") - - -### Signals - - -func _on_theme_changed() -> void: - apply_theme() - - -func _on_filter_edit_text_changed(new_text: String) -> void: - self.filter = new_text - - -func _on_list_item_clicked(index: int, at_position: Vector2, mouse_button_index: int) -> void: - if mouse_button_index == MOUSE_BUTTON_LEFT: - var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") - var file = file_map.find_key(item_text) - select_file(file) - file_selected.emit(file) - - if mouse_button_index == MOUSE_BUTTON_RIGHT: - file_popup_menu_requested.emit(at_position) - - if mouse_button_index == MOUSE_BUTTON_MIDDLE: - var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") - var file = file_map.find_key(item_text) - file_middle_clicked.emit(file) - - -func _on_list_item_activated(index: int) -> void: - var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "") - var file = file_map.find_key(item_text) - select_file(file) - file_double_clicked.emit(file) diff --git a/addons/dialogue_manager/components/files_list.tscn b/addons/dialogue_manager/components/files_list.tscn deleted file mode 100644 index 12bee0b..0000000 --- a/addons/dialogue_manager/components/files_list.tscn +++ /dev/null @@ -1,40 +0,0 @@ -[gd_scene load_steps=5 format=3 uid="uid://dnufpcdrreva3"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/files_list.gd" id="1_cytii"] -[ext_resource type="Texture2D" uid="uid://d3lr2uas6ax8v" path="res://addons/dialogue_manager/assets/icon.svg" id="2_3ijx1"] - -[sub_resource type="Image" id="Image_h3jns"] -data = { -"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), -"format": "RGBA8", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_44sbr"] -image = SubResource("Image_h3jns") - -[node name="FilesList" type="VBoxContainer"] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("1_cytii") -icon = ExtResource("2_3ijx1") - -[node name="FilterEdit" type="LineEdit" parent="."] -layout_mode = 2 -placeholder_text = "Filter files" -clear_button_enabled = true -right_icon = SubResource("ImageTexture_44sbr") - -[node name="List" type="ItemList" parent="."] -layout_mode = 2 -size_flags_vertical = 3 - -[connection signal="theme_changed" from="." to="." method="_on_theme_changed"] -[connection signal="text_changed" from="FilterEdit" to="." method="_on_filter_edit_text_changed"] -[connection signal="item_activated" from="List" to="." method="_on_list_item_activated"] -[connection signal="item_clicked" from="List" to="." method="_on_list_item_clicked"] diff --git a/addons/dialogue_manager/components/find_in_files.gd b/addons/dialogue_manager/components/find_in_files.gd deleted file mode 100644 index 916b744..0000000 --- a/addons/dialogue_manager/components/find_in_files.gd +++ /dev/null @@ -1,229 +0,0 @@ -@tool -extends Control - -signal result_selected(path: String, cursor: Vector2, length: int) - - -const DialogueConstants = preload("../constants.gd") - - -@export var main_view: Control -@export var code_edit: CodeEdit - -@onready var input: LineEdit = %Input -@onready var search_button: Button = %SearchButton -@onready var match_case_button: CheckBox = %MatchCaseButton -@onready var replace_toggle: CheckButton = %ReplaceToggle -@onready var replace_container: VBoxContainer = %ReplaceContainer -@onready var replace_input: LineEdit = %ReplaceInput -@onready var replace_selected_button: Button = %ReplaceSelectedButton -@onready var replace_all_button: Button = %ReplaceAllButton -@onready var results_container: VBoxContainer = %ResultsContainer -@onready var result_template: HBoxContainer = %ResultTemplate - -var current_results: Dictionary = {}: - set(value): - current_results = value - update_results_view() - if current_results.size() == 0: - replace_selected_button.disabled = true - replace_all_button.disabled = true - else: - replace_selected_button.disabled = false - replace_all_button.disabled = false - get: - return current_results - -var selections: PackedStringArray = [] - - -func prepare() -> void: - input.grab_focus() - - var template_label = result_template.get_node("Label") - template_label.get_theme_stylebox(&"focus").bg_color = code_edit.theme_overrides.current_line_color - template_label.add_theme_font_override(&"normal_font", code_edit.get_theme_font(&"font")) - - replace_toggle.set_pressed_no_signal(false) - replace_container.hide() - - $VBoxContainer/HBoxContainer/FindContainer/Label.text = DialogueConstants.translate(&"search.find") - input.placeholder_text = DialogueConstants.translate(&"search.placeholder") - input.text = "" - search_button.text = DialogueConstants.translate(&"search.find_all") - match_case_button.text = DialogueConstants.translate(&"search.match_case") - replace_toggle.text = DialogueConstants.translate(&"search.toggle_replace") - $VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceLabel.text = DialogueConstants.translate(&"search.replace_with") - replace_input.placeholder_text = DialogueConstants.translate(&"search.replace_placeholder") - replace_input.text = "" - replace_all_button.text = DialogueConstants.translate(&"search.replace_all") - replace_selected_button.text = DialogueConstants.translate(&"search.replace_selected") - - selections.clear() - self.current_results = {} - -#region helpers - - -func update_results_view() -> void: - for child in results_container.get_children(): - child.queue_free() - - for path in current_results.keys(): - var path_label: Label = Label.new() - path_label.text = path - # Show open files - if main_view.open_buffers.has(path): - path_label.text += "(*)" - results_container.add_child(path_label) - for path_result in current_results.get(path): - var result_item: HBoxContainer = result_template.duplicate() - - var checkbox: CheckBox = result_item.get_node("CheckBox") as CheckBox - var key: String = get_selection_key(path, path_result) - checkbox.toggled.connect(func(is_pressed): - if is_pressed: - if not selections.has(key): - selections.append(key) - else: - if selections.has(key): - selections.remove_at(selections.find(key)) - ) - checkbox.set_pressed_no_signal(selections.has(key)) - checkbox.visible = replace_toggle.button_pressed - - var result_label: RichTextLabel = result_item.get_node("Label") as RichTextLabel - var colors: Dictionary = code_edit.theme_overrides - var highlight: String = "" - if replace_toggle.button_pressed: - var matched_word: String = "[bgcolor=" + colors.critical_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + path_result.matched_text + "[/color][/bgcolor]" - highlight = "[s]" + matched_word + "[/s][bgcolor=" + colors.notice_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + replace_input.text + "[/color][/bgcolor]" - else: - highlight = "[bgcolor=" + colors.symbols_color.to_html() + "][color=" + colors.text_color.to_html() + "]" + path_result.matched_text + "[/color][/bgcolor]" - var text: String = path_result.text.substr(0, path_result.index) + highlight + path_result.text.substr(path_result.index + path_result.query.length()) - result_label.text = "%s: %s" % [str(path_result.line).lpad(4), text] - result_label.gui_input.connect(func(event): - if event is InputEventMouseButton and (event as InputEventMouseButton).button_index == MOUSE_BUTTON_LEFT and (event as InputEventMouseButton).double_click: - result_selected.emit(path, Vector2(path_result.index, path_result.line), path_result.query.length()) - ) - - results_container.add_child(result_item) - - -func find_in_files() -> Dictionary: - var results: Dictionary = {} - - var q: String = input.text - var cache = Engine.get_meta("DialogueCache") - var file: FileAccess - for path in cache.get_files(): - var path_results: Array = [] - var lines: PackedStringArray = [] - - if main_view.open_buffers.has(path): - lines = main_view.open_buffers.get(path).text.split("\n") - else: - file = FileAccess.open(path, FileAccess.READ) - lines = file.get_as_text().split("\n") - - for i in range(0, lines.size()): - var index: int = find_in_line(lines[i], q) - while index > -1: - path_results.append({ - line = i, - index = index, - text = lines[i], - matched_text = lines[i].substr(index, q.length()), - query = q - }) - index = find_in_line(lines[i], q, index + q.length()) - - if file != null and file.is_open(): - file.close() - - if path_results.size() > 0: - results[path] = path_results - - return results - - -func get_selection_key(path: String, path_result: Dictionary) -> String: - return "%s-%d-%d" % [path, path_result.line, path_result.index] - - -func find_in_line(line: String, query: String, from_index: int = 0) -> int: - if match_case_button.button_pressed: - return line.find(query, from_index) - else: - return line.findn(query, from_index) - - -func replace_results(only_selected: bool) -> void: - var file: FileAccess - var lines: PackedStringArray = [] - for path in current_results: - if main_view.open_buffers.has(path): - lines = main_view.open_buffers.get(path).text.split("\n") - else: - file = FileAccess.open(path, FileAccess.READ_WRITE) - lines = file.get_as_text().split("\n") - - # Read the results in reverse because we're going to be modifying them as we go - var path_results: Array = current_results.get(path).duplicate() - path_results.reverse() - for path_result in path_results: - var key: String = get_selection_key(path, path_result) - if not only_selected or (only_selected and selections.has(key)): - lines[path_result.line] = lines[path_result.line].substr(0, path_result.index) + replace_input.text + lines[path_result.line].substr(path_result.index + path_result.matched_text.length()) - - var replaced_text: String = "\n".join(lines) - if file != null and file.is_open(): - file.seek(0) - file.store_string(replaced_text) - file.close() - else: - main_view.open_buffers.get(path).text = replaced_text - if main_view.current_file_path == path: - code_edit.text = replaced_text - - current_results = find_in_files() - - -#endregion - -#region signals - - -func _on_search_button_pressed() -> void: - selections.clear() - self.current_results = find_in_files() - - -func _on_input_text_submitted(new_text: String) -> void: - _on_search_button_pressed() - - -func _on_replace_toggle_toggled(toggled_on: bool) -> void: - replace_container.visible = toggled_on - if toggled_on: - replace_input.grab_focus() - update_results_view() - - -func _on_replace_input_text_changed(new_text: String) -> void: - update_results_view() - - -func _on_replace_selected_button_pressed() -> void: - replace_results(true) - - -func _on_replace_all_button_pressed() -> void: - replace_results(false) - - -func _on_match_case_button_toggled(toggled_on: bool) -> void: - _on_search_button_pressed() - - -#endregion diff --git a/addons/dialogue_manager/components/find_in_files.tscn b/addons/dialogue_manager/components/find_in_files.tscn deleted file mode 100644 index 8aaef4b..0000000 --- a/addons/dialogue_manager/components/find_in_files.tscn +++ /dev/null @@ -1,139 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://0n7hwviyyly4"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/find_in_files.gd" id="1_3xicy"] - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_owohg"] -bg_color = Color(0.266667, 0.278431, 0.352941, 0.243137) -corner_detail = 1 - -[node name="FindInFiles" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -script = ExtResource("1_3xicy") - -[node name="VBoxContainer" type="VBoxContainer" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] -layout_mode = 2 - -[node name="FindContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/FindContainer"] -layout_mode = 2 -text = "Find:" - -[node name="Input" type="LineEdit" parent="VBoxContainer/HBoxContainer/FindContainer"] -unique_name_in_owner = true -layout_mode = 2 -clear_button_enabled = true - -[node name="FindToolbar" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/FindContainer"] -layout_mode = 2 - -[node name="SearchButton" type="Button" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Find all..." - -[node name="MatchCaseButton" type="CheckBox" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Match case" - -[node name="Control" type="Control" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="ReplaceToggle" type="CheckButton" parent="VBoxContainer/HBoxContainer/FindContainer/FindToolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Replace" - -[node name="ReplaceContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="ReplaceLabel" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] -layout_mode = 2 -text = "Replace with:" - -[node name="ReplaceInput" type="LineEdit" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_horizontal = 3 -clear_button_enabled = true - -[node name="ReplaceToolbar" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/ReplaceContainer"] -layout_mode = 2 - -[node name="ReplaceSelectedButton" type="Button" parent="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Replace selected" - -[node name="ReplaceAllButton" type="Button" parent="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Replace all" - -[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer"] -layout_mode = 2 - -[node name="ReplaceToolbar" type="HBoxContainer" parent="VBoxContainer/VBoxContainer"] -layout_mode = 2 - -[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 3 -follow_focus = true - -[node name="ResultsContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -theme_override_constants/separation = 0 - -[node name="ResultTemplate" type="HBoxContainer" parent="."] -unique_name_in_owner = true -layout_mode = 0 -offset_left = 155.0 -offset_top = -74.0 -offset_right = 838.0 -offset_bottom = -51.0 - -[node name="CheckBox" type="CheckBox" parent="ResultTemplate"] -layout_mode = 2 - -[node name="Label" type="RichTextLabel" parent="ResultTemplate"] -layout_mode = 2 -size_flags_horizontal = 3 -focus_mode = 2 -theme_override_styles/focus = SubResource("StyleBoxFlat_owohg") -bbcode_enabled = true -text = "Result" -fit_content = true -scroll_active = false - -[connection signal="text_submitted" from="VBoxContainer/HBoxContainer/FindContainer/Input" to="." method="_on_input_text_submitted"] -[connection signal="pressed" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/SearchButton" to="." method="_on_search_button_pressed"] -[connection signal="toggled" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/MatchCaseButton" to="." method="_on_match_case_button_toggled"] -[connection signal="toggled" from="VBoxContainer/HBoxContainer/FindContainer/FindToolbar/ReplaceToggle" to="." method="_on_replace_toggle_toggled"] -[connection signal="text_changed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceInput" to="." method="_on_replace_input_text_changed"] -[connection signal="pressed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar/ReplaceSelectedButton" to="." method="_on_replace_selected_button_pressed"] -[connection signal="pressed" from="VBoxContainer/HBoxContainer/ReplaceContainer/ReplaceToolbar/ReplaceAllButton" to="." method="_on_replace_all_button_pressed"] diff --git a/addons/dialogue_manager/components/parse_result.gd b/addons/dialogue_manager/components/parse_result.gd deleted file mode 100644 index d467cb9..0000000 --- a/addons/dialogue_manager/components/parse_result.gd +++ /dev/null @@ -1,10 +0,0 @@ -class_name DialogueManagerParseResult extends RefCounted - -var imported_paths: PackedStringArray = [] -var using_states: PackedStringArray = [] -var titles: Dictionary = {} -var character_names: PackedStringArray = [] -var first_title: String = "" -var lines: Dictionary = {} -var errors: Array[Dictionary] = [] -var raw_text: String = "" diff --git a/addons/dialogue_manager/components/parser.gd b/addons/dialogue_manager/components/parser.gd deleted file mode 100644 index ad6e3ac..0000000 --- a/addons/dialogue_manager/components/parser.gd +++ /dev/null @@ -1,1780 +0,0 @@ -@tool - -class_name DialogueManagerParser extends Object - - -const DialogueConstants = preload("../constants.gd") -const DialogueSettings = preload("../settings.gd") -const ResolvedLineData = preload("./resolved_line_data.gd") -const ResolvedTagData = preload("./resolved_tag_data.gd") -const DialogueManagerParseResult = preload("./parse_result.gd") - - -var IMPORT_REGEX: RegEx = RegEx.create_from_string("import \"(?<path>[^\"]+)\" as (?<prefix>[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+)") -var USING_REGEX: RegEx = RegEx.create_from_string("using (?<state>.*)") -var VALID_TITLE_REGEX: RegEx = RegEx.create_from_string("^[^\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\{\\}\\[\\]\\;\\:\\\"\\'\\,\\.\\<\\>\\?\\/\\s]+$") -var BEGINS_WITH_NUMBER_REGEX: RegEx = RegEx.create_from_string("^\\d") -var TRANSLATION_REGEX: RegEx = RegEx.create_from_string("\\[ID:(?<tr>.*?)\\]") -var TAGS_REGEX: RegEx = RegEx.create_from_string("\\[#(?<tags>.*?)\\]") -var MUTATION_REGEX: RegEx = RegEx.create_from_string("(?<keyword>do|do!|set) (?<mutation>.*)") -var CONDITION_REGEX: RegEx = RegEx.create_from_string("(if|elif|while|else if) (?<condition>.*)") -var WRAPPED_CONDITION_REGEX: RegEx = RegEx.create_from_string("\\[if (?<condition>.*)\\]") -var REPLACEMENTS_REGEX: RegEx = RegEx.create_from_string("{{(.*?)}}") -var GOTO_REGEX: RegEx = RegEx.create_from_string("=><? (?<jump_to_title>.*)") -var INDENT_REGEX: RegEx = RegEx.create_from_string("^\\t+") -var INLINE_RANDOM_REGEX: RegEx = RegEx.create_from_string("\\[\\[(?<options>.*?)\\]\\]") -var INLINE_CONDITIONALS_REGEX: RegEx = RegEx.create_from_string("\\[if (?<condition>.+?)\\](?<body>.*?)\\[\\/if\\]") - -var TOKEN_DEFINITIONS: Dictionary = { - DialogueConstants.TOKEN_FUNCTION: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*\\("), - DialogueConstants.TOKEN_DICTIONARY_REFERENCE: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*\\["), - DialogueConstants.TOKEN_PARENS_OPEN: RegEx.create_from_string("^\\("), - DialogueConstants.TOKEN_PARENS_CLOSE: RegEx.create_from_string("^\\)"), - DialogueConstants.TOKEN_BRACKET_OPEN: RegEx.create_from_string("^\\["), - DialogueConstants.TOKEN_BRACKET_CLOSE: RegEx.create_from_string("^\\]"), - DialogueConstants.TOKEN_BRACE_OPEN: RegEx.create_from_string("^\\{"), - DialogueConstants.TOKEN_BRACE_CLOSE: RegEx.create_from_string("^\\}"), - DialogueConstants.TOKEN_COLON: RegEx.create_from_string("^:"), - DialogueConstants.TOKEN_COMPARISON: RegEx.create_from_string("^(==|<=|>=|<|>|!=|in )"), - DialogueConstants.TOKEN_ASSIGNMENT: RegEx.create_from_string("^(\\+=|\\-=|\\*=|/=|=)"), - DialogueConstants.TOKEN_NUMBER: RegEx.create_from_string("^\\-?\\d+(\\.\\d+)?"), - DialogueConstants.TOKEN_OPERATOR: RegEx.create_from_string("^(\\+|\\-|\\*|/|%)"), - DialogueConstants.TOKEN_COMMA: RegEx.create_from_string("^,"), - DialogueConstants.TOKEN_DOT: RegEx.create_from_string("^\\."), - DialogueConstants.TOKEN_STRING: RegEx.create_from_string("^(\".*?\"|\'.*?\')"), - DialogueConstants.TOKEN_NOT: RegEx.create_from_string("^(not( |$)|!)"), - DialogueConstants.TOKEN_AND_OR: RegEx.create_from_string("^(and|or)( |$)"), - DialogueConstants.TOKEN_VARIABLE: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*"), - DialogueConstants.TOKEN_COMMENT: RegEx.create_from_string("^#.*"), - DialogueConstants.TOKEN_CONDITION: RegEx.create_from_string("^(if|elif|else)"), - DialogueConstants.TOKEN_BOOL: RegEx.create_from_string("^(true|false)") -} - -var WEIGHTED_RANDOM_SIBLINGS_REGEX: RegEx = RegEx.create_from_string("^\\%(?<weight>[\\d.]+)? ") - -var raw_lines: PackedStringArray = [] -var parent_stack: Array[String] = [] - -var parsed_lines: Dictionary = {} -var imported_paths: PackedStringArray = [] -var using_states: PackedStringArray = [] -var titles: Dictionary = {} -var character_names: PackedStringArray = [] -var first_title: String = "" -var errors: Array[Dictionary] = [] -var raw_text: String = "" - -var _imported_line_map: Dictionary = {} -var _imported_line_count: int = 0 - -var while_loopbacks: Array[String] = [] - - -## Parse some raw dialogue text. Returns a dictionary containing parse results -static func parse_string(string: String, path: String) -> DialogueManagerParseResult: - var parser: DialogueManagerParser = DialogueManagerParser.new() - var error: Error = parser.parse(string, path) - var data: DialogueManagerParseResult = parser.get_data() - parser.free() - - if error == OK: - return data - else: - return null - - -## Extract bbcode and other markers from a string -static func extract_markers_from_string(string: String) -> ResolvedLineData: - var parser: DialogueManagerParser = DialogueManagerParser.new() - var markers: ResolvedLineData = parser.extract_markers(string) - parser.free() - - return markers - - -## Parse some raw dialogue text. Returns a dictionary containing parse results -func parse(text: String, path: String) -> Error: - prepare(text, path) - raw_text = text - - # Parse all of the content - var known_translations = {} - - # Get list of known autoloads - var autoload_names: PackedStringArray = get_autoload_names() - - # Keep track of the last doc comment - var doc_comments: Array[String] = [] - - # Then parse all lines - for id in range(0, raw_lines.size()): - var raw_line: String = raw_lines[id] - - var line: Dictionary = { - id = str(id), - next_id = DialogueConstants.ID_NULL - } - - # Work out if we are inside a conditional or option or if we just - # indented back out of one - var indent_size: int = get_indent(raw_line) - if indent_size < parent_stack.size() and not is_line_empty(raw_line): - for _tab in range(0, parent_stack.size() - indent_size): - parent_stack.pop_back() - - # If we are indented then this line should know about its parent - if parent_stack.size() > 0: - line["parent_id"] = parent_stack.back() - - # Trim any indentation (now that we've calculated it) so we can check - # the begining of each line for its type - raw_line = raw_line.strip_edges(true, false) - - # Grab translations - var translation_key: String = extract_translation(raw_line) - if translation_key != "": - line["translation_key"] = translation_key - raw_line = raw_line.replace("[ID:%s]" % translation_key, "") - - # Check for each kind of line - - # Start shortcuts - if raw_line.begins_with("using "): - var using_match: RegExMatch = USING_REGEX.search(raw_line) - if "state" in using_match.names: - var using_state: String = using_match.strings[using_match.names.state].strip_edges() - if not using_state in autoload_names: - add_error(id, 0, DialogueConstants.ERR_UNKNOWN_USING) - elif not using_state in using_states: - using_states.append(using_state) - continue - - # Response - elif is_response_line(raw_line): - # Add any doc notes - line["notes"] = "\n".join(doc_comments) - doc_comments = [] - - parent_stack.append(str(id)) - line["type"] = DialogueConstants.TYPE_RESPONSE - - # Extract any #tags - var tag_data: ResolvedTagData = extract_tags(raw_line) - line["tags"] = tag_data.tags - raw_line = tag_data.line_without_tags - - if " [if " in raw_line: - line["condition"] = extract_condition(raw_line, true, indent_size) - if " =>" in raw_line: - line["next_id"] = extract_goto(raw_line) - if " =><" in raw_line: - # Because of when the return point needs to be known at runtime we need to split - # this line into two (otherwise the return point would be dependent on the balloon) - var goto_line: Dictionary = { - type = DialogueConstants.TYPE_GOTO, - next_id = extract_goto(raw_line), - next_id_after = find_next_line_after_responses(id), - is_snippet = true - } - parsed_lines[str(id) + ".1"] = goto_line - line["next_id"] = str(id) + ".1" - - # Make sure the added goto line can actually go to somewhere - if goto_line.next_id in [DialogueConstants.ID_ERROR, DialogueConstants.ID_ERROR_INVALID_TITLE, DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY]: - line["next_id"] = goto_line.next_id - - line["character"] = "" - line["character_replacements"] = [] as Array[Dictionary] - line["text"] = extract_response_prompt(raw_line) - - var previous_response_id = find_previous_response_id(id) - if parsed_lines.has(previous_response_id): - var previous_response = parsed_lines[previous_response_id] - # Add this response to the list on the first response so that it is the - # authority on what is in the list of responses - previous_response["responses"] = previous_response["responses"] + PackedStringArray([str(id)]) - else: - # No previous response so this is the first in the list - line["responses"] = PackedStringArray([str(id)]) - - line["next_id_after"] = find_next_line_after_responses(id) - - # If this response has no body then the next id is the next id after - if not line.has("next_id") or line.next_id == DialogueConstants.ID_NULL: - var next_nonempty_line_id = get_next_nonempty_line_id(id) - if next_nonempty_line_id != DialogueConstants.ID_NULL: - if get_indent(raw_lines[next_nonempty_line_id.to_int()]) <= indent_size: - line["next_id"] = line.next_id_after - else: - line["next_id"] = next_nonempty_line_id - - line["text_replacements"] = extract_dialogue_replacements(line.get("text"), indent_size + 2) - for replacement in line.text_replacements: - if replacement.has("error"): - add_error(id, replacement.index, replacement.error) - - # If this response has a character name in it then it will automatically be - # injected as a line of dialogue if the player selects it - var response_text: String = line.text.replace("\\:", "!ESCAPED_COLON!") - if ": " in response_text: - if DialogueSettings.get_setting("create_lines_for_responses_with_characters", true): - var first_child: Dictionary = { - type = DialogueConstants.TYPE_DIALOGUE, - next_id = line.next_id, - next_id_after = line.next_id_after, - text_replacements = line.text_replacements, - tags = line.tags, - translation_key = line.get("translation_key") - } - parse_response_character_and_text(id, response_text, first_child, indent_size, parsed_lines) - line["character"] = first_child.character - line["character_replacements"] = first_child.character_replacements - line["text"] = first_child.text - line["translation_key"] = first_child.translation_key - parsed_lines[str(id) + ".2"] = first_child - line["next_id"] = str(id) + ".2" - else: - parse_response_character_and_text(id, response_text, line, indent_size, parsed_lines) - else: - line["text"] = response_text.replace("!ESCAPED_COLON!", ":") - - # Title - elif is_title_line(raw_line): - line["type"] = DialogueConstants.TYPE_TITLE - if not raw_lines[id].begins_with("~"): - add_error(id, indent_size + 2, DialogueConstants.ERR_NESTED_TITLE) - else: - line["text"] = extract_title(raw_line) - # Titles can't have numbers as the first letter (unless they are external titles which get replaced with hashes) - if id >= _imported_line_count and BEGINS_WITH_NUMBER_REGEX.search(line.text): - add_error(id, 2, DialogueConstants.ERR_TITLE_BEGINS_WITH_NUMBER) - # Only import titles are allowed to have "/" in them - var valid_title = VALID_TITLE_REGEX.search(raw_line.replace("/", "").substr(2).strip_edges()) - if not valid_title: - add_error(id, 2, DialogueConstants.ERR_TITLE_INVALID_CHARACTERS) - - # Condition - elif is_condition_line(raw_line, false): - parent_stack.append(str(id)) - line["type"] = DialogueConstants.TYPE_CONDITION - line["condition"] = extract_condition(raw_line, false, indent_size) - line["next_id_after"] = find_next_line_after_conditions(id) - var next_sibling_id = find_next_condition_sibling(id) - line["next_conditional_id"] = next_sibling_id if is_valid_id(next_sibling_id) else line.next_id_after - - elif is_condition_line(raw_line, true): - parent_stack.append(str(id)) - line["type"] = DialogueConstants.TYPE_CONDITION - line["next_id_after"] = find_next_line_after_conditions(id) - line["next_conditional_id"] = line["next_id_after"] - - elif is_while_condition_line(raw_line): - parent_stack.append(str(id)) - line["type"] = DialogueConstants.TYPE_CONDITION - line["condition"] = extract_condition(raw_line, false, indent_size) - line["next_id_after"] = find_next_line_after_conditions(id) - while_loopbacks.append(find_last_line_within_conditions(id)) - line["next_conditional_id"] = line["next_id_after"] - - # Mutation - elif is_mutation_line(raw_line): - line["type"] = DialogueConstants.TYPE_MUTATION - line["mutation"] = extract_mutation(raw_line) - - # Goto - elif is_goto_line(raw_line): - line["type"] = DialogueConstants.TYPE_GOTO - - if raw_line.begins_with("%"): - apply_weighted_random(id, raw_line, indent_size, line) - - line["next_id"] = extract_goto(raw_line) - if is_goto_snippet_line(raw_line): - line["is_snippet"] = true - line["next_id_after"] = get_line_after_line(id, indent_size, line) - else: - line["is_snippet"] = false - - # Nested dialogue - elif is_nested_dialogue_line(raw_line, parsed_lines, raw_lines, indent_size): - var parent_line: Dictionary = parsed_lines.values().back() - var parent_indent_size: int = get_indent(raw_lines[parent_line.id.to_int()]) - var should_update_translation_key: bool = parent_line.translation_key == parent_line.text - var suffix: String = raw_line.strip_edges(true, false) - if suffix == "": - suffix = " " - parent_line["text"] += "\n" + suffix - parent_line["text_replacements"] = extract_dialogue_replacements(parent_line.text, parent_line.character.length() + 2 + parent_indent_size) - for replacement in parent_line.text_replacements: - if replacement.has("error"): - add_error(id, replacement.index, replacement.error) - - if should_update_translation_key: - parent_line["translation_key"] = parent_line.text - - parent_line["next_id"] = get_line_after_line(id, parent_indent_size, parent_line) - - # Ignore this line when checking for indent errors - remove_error(parent_line.id.to_int(), DialogueConstants.ERR_INVALID_INDENTATION) - - var next_line = raw_lines[parent_line.next_id.to_int()] - if not is_dialogue_line(next_line) and get_indent(next_line) >= indent_size: - add_error(parent_line.next_id.to_int(), indent_size, DialogueConstants.ERR_INVALID_INDENTATION) - - continue - - elif raw_line.strip_edges().begins_with("##"): - doc_comments.append(raw_line.replace("##", "").strip_edges()) - continue - - elif is_line_empty(raw_line) or is_import_line(raw_line): - continue - - # Regular dialogue - else: - # Remove escape character - if raw_line.begins_with("\\using"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\if"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\elif"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\else"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\while"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\-"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\~"): raw_line = raw_line.substr(1) - if raw_line.begins_with("\\=>"): raw_line = raw_line.substr(1) - - # Add any doc notes - line["notes"] = "\n".join(doc_comments) - doc_comments = [] - - # Work out any weighted random siblings - if raw_line.begins_with("%"): - apply_weighted_random(id, raw_line, indent_size, line) - raw_line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_line, "") - - line["type"] = DialogueConstants.TYPE_DIALOGUE - - # Extract any tags before we process the line - var tag_data: ResolvedTagData = extract_tags(raw_line) - line["tags"] = tag_data.tags - raw_line = tag_data.line_without_tags - - var l = raw_line.replace("\\:", "!ESCAPED_COLON!") - if ": " in l: - var bits = Array(l.strip_edges().split(": ")) - line["character"] = bits.pop_front().strip_edges() - if not line["character"] in character_names: - character_names.append(line["character"]) - # You can use variables in the character's name - line["character_replacements"] = extract_dialogue_replacements(line.character, indent_size) - for replacement in line.character_replacements: - if replacement.has("error"): - add_error(id, replacement.index, replacement.error) - line["text"] = ": ".join(bits).replace("!ESCAPED_COLON!", ":") - else: - line["character"] = "" - line["character_replacements"] = [] as Array[Dictionary] - line["text"] = l.replace("!ESCAPED_COLON!", ":") - - line["text_replacements"] = extract_dialogue_replacements(line.text, line.character.length() + 2 + indent_size) - for replacement in line.text_replacements: - if replacement.has("error"): - add_error(id, replacement.index, replacement.error) - - # Unescape any newlines - line["text"] = line.text.replace("\\n", "\n").strip_edges() - - # Work out where to go after this line - if line.next_id == DialogueConstants.ID_NULL: - line["next_id"] = get_line_after_line(id, indent_size, line) - - # Check for duplicate translation keys - if line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: - if line.has("translation_key"): - if known_translations.has(line.translation_key) and known_translations.get(line.translation_key) != line.text: - add_error(id, indent_size, DialogueConstants.ERR_DUPLICATE_ID) - else: - known_translations[line.translation_key] = line.text - else: - # Default translations key - if DialogueSettings.get_setting("missing_translations_are_errors", false): - add_error(id, indent_size, DialogueConstants.ERR_MISSING_ID) - else: - line["translation_key"] = line.text - - ## Error checking - - # Can't find goto - var jump_index: int = raw_line.find("=>") - match line.next_id: - DialogueConstants.ID_ERROR: - add_error(id, jump_index, DialogueConstants.ERR_UNKNOWN_TITLE) - DialogueConstants.ID_ERROR_INVALID_TITLE: - add_error(id, jump_index, DialogueConstants.ERR_INVALID_TITLE_REFERENCE) - DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY: - add_error(id, jump_index, DialogueConstants.ERR_TITLE_REFERENCE_HAS_NO_CONTENT) - - # Line after condition isn't indented once to the right - if line.type == DialogueConstants.TYPE_CONDITION: - if is_valid_id(line.next_id): - var next_line: String = raw_lines[line.next_id.to_int()] - var next_indent: int = get_indent(next_line) - if next_indent != indent_size + 1: - add_error(line.next_id.to_int(), next_indent, DialogueConstants.ERR_INVALID_INDENTATION) - else: - add_error(id, indent_size, DialogueConstants.ERR_INVALID_CONDITION_INDENTATION) - - # Line after normal line is indented to the right - elif line.type in [ - DialogueConstants.TYPE_TITLE, - DialogueConstants.TYPE_DIALOGUE, - DialogueConstants.TYPE_MUTATION, - DialogueConstants.TYPE_GOTO - ] and is_valid_id(line.next_id): - var next_line = raw_lines[line.next_id.to_int()] - if next_line != null and get_indent(next_line) > indent_size: - add_error(id, indent_size, DialogueConstants.ERR_INVALID_INDENTATION) - - # Parsing condition failed - if line.has("condition") and line.condition.has("error"): - add_error(id, line.condition.index, line.condition.error) - - # Parsing mutation failed - elif line.has("mutation") and line.mutation.has("error"): - add_error(id, line.mutation.index, line.mutation.error) - - # Line failed to parse at all - if line.get("type") == DialogueConstants.TYPE_UNKNOWN: - add_error(id, 0, DialogueConstants.ERR_UNKNOWN_LINE_SYNTAX) - - # If there are no titles then use the first actual line - if first_title == "" and not is_import_line(raw_line): - first_title = str(id) - - # If this line is the last line of a while loop, edit the id of its next line - if str(id) in while_loopbacks: - if is_goto_snippet_line(raw_line): - line["next_id_after"] = line["parent_id"] - elif is_condition_line(raw_line, true) or is_while_condition_line(raw_line): - line["next_conditional_id"] = line["parent_id"] - line["next_id_after"] = line["parent_id"] - elif is_goto_line(raw_line) or is_title_line(raw_line): - pass - else: - line["next_id"] = line["parent_id"] - - # Done! - parsed_lines[str(id)] = line - - # Assume the last line ends the dialogue - var last_line: Dictionary = parsed_lines.values()[parsed_lines.values().size() - 1] - if last_line.next_id == "": - last_line.next_id = DialogueConstants.ID_END - - if errors.size() > 0: - return ERR_PARSE_ERROR - - return OK - - -func get_data() -> DialogueManagerParseResult: - var data: DialogueManagerParseResult = DialogueManagerParseResult.new() - data.imported_paths = imported_paths - data.using_states = using_states - data.titles = titles - data.character_names = character_names - data.first_title = first_title - data.lines = parsed_lines - data.errors = errors - data.raw_text = raw_text - return data - - -## Get the last parse errors -func get_errors() -> Array[Dictionary]: - return errors - - -## Prepare the parser by collecting all lines and titles -func prepare(text: String, path: String, include_imported_titles_hashes: bool = true) -> void: - using_states = [] - errors = [] - imported_paths = [] - _imported_line_map = {} - while_loopbacks = [] - titles = {} - character_names = [] - first_title = "" - raw_lines = text.split("\n") - - # Work out imports - var known_imports: Dictionary = {} - - # Include the base file path so that we can get around circular dependencies - known_imports[path.hash()] = "." - - var imported_titles: Dictionary = {} - for id in range(0, raw_lines.size()): - var line = raw_lines[id] - if is_import_line(line): - var import_data = extract_import_path_and_name(line) - var import_hash: int = import_data.path.hash() - if import_data.size() > 0: - # Keep track of titles so we can add imported ones later - if str(import_hash) in imported_titles.keys(): - add_error(id, 0, DialogueConstants.ERR_FILE_ALREADY_IMPORTED) - if import_data.prefix in imported_titles.values(): - add_error(id, 0, DialogueConstants.ERR_DUPLICATE_IMPORT_NAME) - imported_titles[str(import_hash)] = import_data.prefix - - # Import the file content - if not known_imports.has(import_hash): - var error: Error = import_content(import_data.path, import_data.prefix, _imported_line_map, known_imports) - if error != OK: - add_error(id, 0, error) - - # Make a map so we can refer compiled lines to where they were imported from - if not _imported_line_map.has(import_hash): - _imported_line_map[import_hash] = { - hash = import_hash, - imported_on_line_number = id, - from_line = 0, - to_line = 0 - } - - var imported_content: String = "" - var cummulative_line_number: int = 0 - for item in _imported_line_map.values(): - item["from_line"] = cummulative_line_number - if known_imports.has(item.hash): - cummulative_line_number += known_imports[item.hash].split("\n").size() - item["to_line"] = cummulative_line_number - if known_imports.has(item.hash): - imported_content += known_imports[item.hash] + "\n" - - _imported_line_count = cummulative_line_number + 1 - - # Join it with the actual content - raw_lines = (imported_content + "\n" + text).split("\n") - - # Find all titles first - for id in range(0, raw_lines.size()): - if raw_lines[id].begins_with("~ "): - var title: String = extract_title(raw_lines[id]) - if title == "": - add_error(id, 2, DialogueConstants.ERR_EMPTY_TITLE) - elif titles.has(title): - add_error(id, 2, DialogueConstants.ERR_DUPLICATE_TITLE) - else: - var next_nonempty_line_id: String = get_next_nonempty_line_id(id) - if next_nonempty_line_id != DialogueConstants.ID_NULL: - titles[title] = next_nonempty_line_id - if "/" in title: - if include_imported_titles_hashes == false: - titles.erase(title) - var bits: PackedStringArray = title.split("/") - if imported_titles.has(bits[0]): - title = imported_titles[bits[0]] + "/" + bits[1] - titles[title] = next_nonempty_line_id - elif first_title == "": - first_title = next_nonempty_line_id - else: - titles[title] = DialogueConstants.ID_ERROR_TITLE_HAS_NO_BODY - - -func add_error(line_number: int, column_number: int, error: int) -> void: - # See if the error was in an imported file - for item in _imported_line_map.values(): - if line_number < item.to_line: - errors.append({ - line_number = item.imported_on_line_number, - column_number = 0, - error = DialogueConstants.ERR_ERRORS_IN_IMPORTED_FILE, - external_error = error, - external_line_number = line_number - }) - return - - # Otherwise, it's in this file - errors.append({ - line_number = line_number - _imported_line_count, - column_number = column_number, - error = error - }) - - -func remove_error(line_number: int, error: int) -> void: - for i in range(errors.size() - 1, -1, -1): - var err = errors[i] - var is_native_error = err.line_number == line_number - _imported_line_count and err.error == error - var is_external_error = err.get("external_line_number") == line_number and err.get("external_error") == error - if is_native_error or is_external_error: - errors.remove_at(i) - return - - -func is_import_line(line: String) -> bool: - return line.begins_with("import ") and " as " in line - - -func is_title_line(line: String) -> bool: - return line.strip_edges(true, false).begins_with("~ ") - - -func is_condition_line(line: String, include_else: bool = true) -> bool: - line = line.strip_edges(true, false) - if line.begins_with("if ") or line.begins_with("elif ") or line.begins_with("else if"): return true - if include_else and line.begins_with("else"): return true - return false - -func is_while_condition_line(line: String) -> bool: - line = line.strip_edges(true, false) - if line.begins_with("while "): return true - return false - - -func is_mutation_line(line: String) -> bool: - line = line.strip_edges(true, false) - return line.begins_with("do ") or line.begins_with("do! ") or line.begins_with("set ") - - -func is_goto_line(line: String) -> bool: - line = line.strip_edges(true, false) - line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(line, "") - return line.begins_with("=> ") or line.begins_with("=>< ") - - -func is_goto_snippet_line(line: String) -> bool: - line = WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(line.strip_edges(), "") - return line.begins_with("=>< ") - - -func is_nested_dialogue_line(raw_line: String, parsed_lines: Dictionary, raw_lines: PackedStringArray, indent_size: int) -> bool: - if parsed_lines.values().is_empty(): return false - if raw_line.strip_edges().begins_with("#"): return false - - var parent_line: Dictionary = parsed_lines.values().back() - if parent_line.type != DialogueConstants.TYPE_DIALOGUE: return false - if get_indent(raw_lines[parent_line.id.to_int()]) >= indent_size: return false - return true - - -func is_dialogue_line(line: String) -> bool: - if line == null: return false - if is_response_line(line): return false - if is_title_line(line): return false - if is_condition_line(line, true): return false - if is_mutation_line(line): return false - if is_goto_line(line): return false - return true - - -func is_response_line(line: String) -> bool: - return line.strip_edges(true, false).begins_with("- ") - - -func is_valid_id(id: String) -> bool: - return false if id in [DialogueConstants.ID_NULL, DialogueConstants.ID_ERROR, DialogueConstants.ID_END_CONVERSATION] else true - - -func is_line_empty(line: String) -> bool: - line = line.strip_edges() - - if line == "": return true - if line == "endif": return true - if line.begins_with("#"): return true - - return false - - -func get_line_after_line(id: int, indent_size: int, line: Dictionary) -> String: - # Unless the next line is an outdent we can assume it comes next - var next_nonempty_line_id = get_next_nonempty_line_id(id) - if next_nonempty_line_id != DialogueConstants.ID_NULL \ - and indent_size <= get_indent(raw_lines[next_nonempty_line_id.to_int()]): - # The next line is a title so we need the next nonempty line after that - if is_title_line(raw_lines[next_nonempty_line_id.to_int()]): - return get_next_nonempty_line_id(next_nonempty_line_id.to_int()) - # Otherwise it's a normal line - else: - return next_nonempty_line_id - # Otherwise, we grab the ID from the parents next ID after children - elif line.has("parent_id") and parsed_lines.has(line.parent_id): - return parsed_lines[line.parent_id].next_id_after - - else: - return DialogueConstants.ID_NULL - - -func get_indent(line: String) -> int: - var tabs: RegExMatch = INDENT_REGEX.search(line) - if tabs: - return tabs.get_string().length() - else: - return 0 - - -func get_next_nonempty_line_id(line_number: int) -> String: - for i in range(line_number + 1, raw_lines.size()): - if not is_line_empty(raw_lines[i]): - return str(i) - return DialogueConstants.ID_NULL - - -func find_previous_response_id(line_number: int) -> String: - var line = raw_lines[line_number] - var indent_size = get_indent(line) - - # Look back up the list to find the previous response - var last_found_response_id: String = str(line_number) - - for i in range(line_number - 1, -1, -1): - line = raw_lines[i] - - if is_line_empty(line): continue - - # If its a response at the same indent level then its a match - elif get_indent(line) == indent_size: - if line.strip_edges().begins_with("- "): - last_found_response_id = str(i) - else: - return last_found_response_id - - # Return itself if nothing was found - return last_found_response_id - - -func apply_weighted_random(id: int, raw_line: String, indent_size: int, line: Dictionary) -> void: - var weight: float = 1 - var found = WEIGHTED_RANDOM_SIBLINGS_REGEX.search(raw_line) - if found and found.names.has("weight"): - weight = found.strings[found.names.weight].to_float() - - # Look back up the list to find the first weighted random line in this group - var original_random_line: Dictionary = {} - for i in range(id, 0, -1): - # Ignore doc comment lines - if raw_lines[i].strip_edges().begins_with("##"): - continue - # Lines that aren't prefixed with the random token are a dead end - if not raw_lines[i].strip_edges().begins_with("%") or get_indent(raw_lines[i]) != indent_size: - break - # Make sure we group random dialogue and random lines separately - elif WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_line.strip_edges(), "").begins_with("=") != WEIGHTED_RANDOM_SIBLINGS_REGEX.sub(raw_lines[i].strip_edges(), "").begins_with("="): - break - # Otherwise we've found the origin - elif parsed_lines.has(str(i)) and parsed_lines[str(i)].has("siblings"): - original_random_line = parsed_lines[str(i)] - break - - # Attach it to the original random line and work out where to go after the line - if original_random_line.size() > 0: - original_random_line["siblings"] += [{ weight = weight, id = str(id) }] - if original_random_line.type != DialogueConstants.TYPE_GOTO: - # Update the next line for all siblings (not goto lines, though, they manager their - # own next ID) - original_random_line["next_id"] = get_line_after_line(id, indent_size, line) - for sibling in original_random_line["siblings"]: - if sibling.id in parsed_lines: - parsed_lines[sibling.id]["next_id"] = original_random_line["next_id"] - line["next_id"] = original_random_line.next_id - # Or set up this line as the original - else: - line["siblings"] = [{ weight = weight, id = str(id) }] - line["next_id"] = get_line_after_line(id, indent_size, line) - - if line.next_id == DialogueConstants.ID_NULL: - line["next_id"] = DialogueConstants.ID_END - - -func find_next_condition_sibling(line_number: int) -> String: - var line = raw_lines[line_number] - var expected_indent = get_indent(line) - - # Look down the list and find an elif or else at the same indent level - for i in range(line_number + 1, raw_lines.size()): - line = raw_lines[i] - if is_line_empty(line): continue - - var l = line.strip_edges() - if l.begins_with("~ "): - return DialogueConstants.ID_END_CONVERSATION - - elif get_indent(line) < expected_indent: - return DialogueConstants.ID_NULL - - elif get_indent(line) == expected_indent: - # Found an if, which begins a different block - if l.begins_with("if"): - return DialogueConstants.ID_NULL - - # Found what we're looking for - elif (l.begins_with("elif ") or l.begins_with("else")): - return str(i) - - return DialogueConstants.ID_NULL - - -func find_next_line_after_conditions(line_number: int) -> String: - var line = raw_lines[line_number] - var expected_indent = get_indent(line) - - # Look down the list for the first non condition line at the same or less indent level - for i in range(line_number + 1, raw_lines.size()): - line = raw_lines[i] - - if is_line_empty(line): continue - - var line_indent = get_indent(line) - line = line.strip_edges() - - if is_title_line(line): - return get_next_nonempty_line_id(i) - - elif line_indent > expected_indent: - continue - - elif line_indent == expected_indent: - if line.begins_with("elif ") or line.begins_with("else"): - continue - else: - return str(i) - - elif line_indent < expected_indent: - # We have to check the parent of this block - for p in range(line_number - 1, -1, -1): - line = raw_lines[p] - - if is_line_empty(line): continue - - line_indent = get_indent(line) - if line_indent < expected_indent: - return parsed_lines[str(p)].get("next_id_after", DialogueConstants.ID_NULL) - - return DialogueConstants.ID_END_CONVERSATION - -func find_last_line_within_conditions(line_number: int) -> String: - var line = raw_lines[line_number] - var expected_indent = get_indent(line) - - var candidate = DialogueConstants.ID_NULL - - # Look down the list for the last line that has an indent level 1 more than this line - # Ending the search when you find a line the same or less indent level - for i in range(line_number + 1, raw_lines.size()): - line = raw_lines[i] - - if is_line_empty(line): continue - - var line_indent = get_indent(line) - line = line.strip_edges() - - if line_indent > expected_indent + 1: - continue - elif line_indent == (expected_indent + 1): - candidate = i - else: - break - - return str(candidate) - -func find_next_line_after_responses(line_number: int) -> String: - var line = raw_lines[line_number] - var expected_indent = get_indent(line) - - # Find the first line after this one that has a smaller indent that isn't another option - # If we hit the eof then we give up - for i in range(line_number + 1, raw_lines.size()): - line = raw_lines[i] - - if is_line_empty(line): continue - - var indent = get_indent(line) - - line = line.strip_edges() - - # We hit a title so the next line is a new start - if is_title_line(line): - return get_next_nonempty_line_id(i) - - # Another option - elif line.begins_with("- "): - if indent == expected_indent: - # ...at the same level so we continue - continue - elif indent < expected_indent: - # ...outdented so check the previous parent - var previous_parent = parent_stack[parent_stack.size() - 2] - if parsed_lines.has(str(previous_parent)): - return parsed_lines[str(previous_parent)].next_id_after - else: - return DialogueConstants.ID_NULL - - # We're at the end of a conditional so jump back up to see what's after it - elif line.begins_with("elif ") or line.begins_with("else"): - for p in range(line_number - 1, -1, -1): - line = raw_lines[p] - - if is_line_empty(line): continue - - var line_indent = get_indent(line) - if line_indent < expected_indent: - return parsed_lines[str(p)].next_id_after - - # Otherwise check the indent for an outdent - else: - line_number = i - line = raw_lines[line_number] - if get_indent(line) <= expected_indent: - return str(line_number) - - # EOF so must be end of conversation - return DialogueConstants.ID_END_CONVERSATION - - -## Get the names of any autoloads in the project -func get_autoload_names() -> PackedStringArray: - var autoloads: PackedStringArray = [] - - var project = ConfigFile.new() - project.load("res://project.godot") - if project.has_section("autoload"): - return Array(project.get_section_keys("autoload")).filter(func(key): return key != "DialogueManager") - - return autoloads - - -## Import content from another dialogue file or return an ERR -func import_content(path: String, prefix: String, imported_line_map: Dictionary, known_imports: Dictionary) -> Error: - if FileAccess.file_exists(path): - var file = FileAccess.open(path, FileAccess.READ) - var content: PackedStringArray = file.get_as_text().split("\n") - - var imported_titles: Dictionary = {} - - for index in range(0, content.size()): - var line = content[index] - if is_import_line(line): - var import = extract_import_path_and_name(line) - if import.size() > 0: - if not known_imports.has(import.path.hash()): - # Add an empty record into the keys just so we don't end up with cyclic dependencies - known_imports[import.path.hash()] = "" - if import_content(import.path, import.prefix, imported_line_map, known_imports) != OK: - return ERR_LINK_FAILED - - if not imported_line_map.has(import.path.hash()): - # Make a map so we can refer compiled lines to where they were imported from - imported_line_map[import.path.hash()] = { - hash = import.path.hash(), - imported_on_line_number = index, - from_line = 0, - to_line = 0 - } - - imported_titles[import.prefix] = import.path.hash() - - var origin_hash: int = -1 - for hash_value in known_imports.keys(): - if known_imports[hash_value] == ".": - origin_hash = hash_value - - # Replace any titles or jump points with references to the files they point to (event if they point to their own file) - for i in range(0, content.size()): - var line = content[i] - if is_title_line(line): - var title = extract_title(line) - if "/" in line: - var bits = title.split("/") - content[i] = "~ %s/%s" % [imported_titles[bits[0]], bits[1]] - else: - content[i] = "~ %s/%s" % [str(path.hash()), title] - - elif "=>< " in line: - var jump: String = line.substr(line.find("=>< ") + "=>< ".length()).strip_edges() - if "/" in jump: - var bits: PackedStringArray = jump.split("/") - var title_hash: int = imported_titles[bits[0]] - if title_hash == origin_hash: - content[i] = "%s=>< %s" % [line.split("=>< ")[0], bits[1]] - else: - content[i] = "%s=>< %s/%s" % [line.split("=>< ")[0], title_hash, bits[1]] - - elif not jump in ["END", "END!"]: - content[i] = "%s=>< %s/%s" % [line.split("=>< ")[0], str(path.hash()), jump] - - elif "=> " in line: - var jump: String = line.substr(line.find("=> ") + "=> ".length()).strip_edges() - if "/" in jump: - var bits: PackedStringArray = jump.split("/") - var title_hash: int = imported_titles[bits[0]] - if title_hash == origin_hash: - content[i] = "%s=> %s" % [line.split("=> ")[0], bits[1]] - else: - content[i] = "%s=> %s/%s" % [line.split("=> ")[0], title_hash, bits[1]] - - elif not jump in ["END", "END!"]: - content[i] = "%s=> %s/%s" % [line.split("=> ")[0], str(path.hash()), jump] - - imported_paths.append(path) - known_imports[path.hash()] = "\n".join(content) + "\n=> END\n" - return OK - else: - return ERR_FILE_NOT_FOUND - - -func extract_import_path_and_name(line: String) -> Dictionary: - var found: RegExMatch = IMPORT_REGEX.search(line) - if found: - return { - path = found.strings[found.names.path], - prefix = found.strings[found.names.prefix] - } - else: - return {} - - -func extract_title(line: String) -> String: - return line.substr(2).strip_edges() - - -func extract_translation(line: String) -> String: - # Find a static translation key, eg. [ID:something] - var found: RegExMatch = TRANSLATION_REGEX.search(line) - if found: - return found.strings[found.names.tr] - else: - return "" - - -func extract_response_prompt(line: String) -> String: - # Find just the text prompt from a response, ignoring any conditions or gotos - line = line.substr(2) - if " [if " in line: - line = line.substr(0, line.find(" [if ")) - if " =>" in line: - line = line.substr(0, line.find(" =>")) - - # Without the translation key if there is one - var translation_key: String = extract_translation(line) - if translation_key: - line = line.replace("[ID:%s]" % translation_key, "") - - return line.replace("\\n", "\n").strip_edges() - - -func parse_response_character_and_text(id: int, text: String, line: Dictionary, indent_size: int, parsed_lines: Dictionary) -> void: - var bits = Array(text.strip_edges().split(": ")) - line["character"] = bits.pop_front().strip_edges() - line["character_replacements"] = extract_dialogue_replacements(line.character, line.character.length() + 2 + indent_size) - for replacement in line.character_replacements: - if replacement.has("error"): - add_error(id, replacement.index, replacement.error) - - if not line["character"] in character_names: - character_names.append(line["character"]) - - line["text"] = ": ".join(bits).replace("!ESCAPED_COLON!", ":").strip_edges() - - if line.get("translation_key", null) == null: - line["translation_key"] = line.text - - -func extract_mutation(line: String) -> Dictionary: - var found: RegExMatch = MUTATION_REGEX.search(line) - - if not found: - return { - index = 0, - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - - if found.names.has("mutation"): - var expression: Array = tokenise(found.strings[found.names.mutation], DialogueConstants.TYPE_MUTATION, found.get_start("mutation")) - if expression.size() == 0: - return { - index = found.get_start("mutation"), - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - elif expression[0].type == DialogueConstants.TYPE_ERROR: - return { - index = expression[0].index, - error = expression[0].value - } - else: - return { - expression = expression, - is_blocking = not "!" in found.strings[found.names.keyword] - } - - else: - return { - index = found.get_start(), - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - - -func extract_condition(raw_line: String, is_wrapped: bool, index: int) -> Dictionary: - var condition: Dictionary = {} - - var regex: RegEx = WRAPPED_CONDITION_REGEX if is_wrapped else CONDITION_REGEX - var found: RegExMatch = regex.search(raw_line) - - if found == null: - return { - index = 0, - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - - var raw_condition: String = found.strings[found.names.condition] - var expression: Array = tokenise(raw_condition, DialogueConstants.TYPE_CONDITION, index + found.get_start("condition")) - - if expression.size() == 0: - return { - index = index + found.get_start("condition"), - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - elif expression[0].type == DialogueConstants.TYPE_ERROR: - return { - index = expression[0].index, - error = expression[0].value - } - else: - return { - expression = expression - } - - -func extract_dialogue_replacements(text: String, index: int) -> Array[Dictionary]: - var founds: Array[RegExMatch] = REPLACEMENTS_REGEX.search_all(text) - - if founds == null or founds.size() == 0: - return [] - - var replacements: Array[Dictionary] = [] - for found in founds: - var replacement: Dictionary = {} - var value_in_text: String = found.strings[1] - var expression: Array = tokenise(value_in_text, DialogueConstants.TYPE_DIALOGUE, index + found.get_start(1)) - if expression.size() == 0: - replacement = { - index = index + found.get_start(1), - error = DialogueConstants.ERR_INCOMPLETE_EXPRESSION - } - elif expression[0].type == DialogueConstants.TYPE_ERROR: - replacement = { - index = expression[0].index, - error = expression[0].value - } - else: - replacement = { - value_in_text = "{{%s}}" % value_in_text, - expression = expression - } - replacements.append(replacement) - - return replacements - - -func extract_goto(line: String) -> String: - var found: RegExMatch = GOTO_REGEX.search(line) - - if found == null: return DialogueConstants.ID_ERROR - - var title: String = found.strings[found.names.jump_to_title].strip_edges() - - if " " in title or title == "": - return DialogueConstants.ID_ERROR_INVALID_TITLE - - # "=> END!" means end the conversation - if title == "END!": - return DialogueConstants.ID_END_CONVERSATION - # "=> END" means end the current title (and go back to the previous one if there is one - # in the stack) - elif title == "END": - return DialogueConstants.ID_END - - elif titles.has(title): - return titles.get(title) - else: - return DialogueConstants.ID_ERROR - - -func extract_tags(line: String) -> ResolvedTagData: - var resolved_tags: PackedStringArray = [] - var tag_matches: Array[RegExMatch] = TAGS_REGEX.search_all(line) - for tag_match in tag_matches: - line = line.replace(tag_match.get_string(), "") - var tags = tag_match.get_string().replace("[#", "").replace("]", "").replace(", ", ",").split(",") - for tag in tags: - tag = tag.replace("#", "") - if not tag in resolved_tags: - resolved_tags.append(tag) - - return ResolvedTagData.new({ - tags = resolved_tags, - line_without_tags = line - }) - - -func extract_markers(line: String) -> ResolvedLineData: - var text: String = line - var pauses: Dictionary = {} - var speeds: Dictionary = {} - var mutations: Array[Array] = [] - var bbcodes: Array = [] - var time: String = "" - - # Remove any escaped brackets (ie. "\[") - var escaped_open_brackets: PackedInt32Array = [] - var escaped_close_brackets: PackedInt32Array = [] - for i in range(0, text.length() - 1): - if text.substr(i, 2) == "\\[": - text = text.substr(0, i) + "!" + text.substr(i + 2) - escaped_open_brackets.append(i) - elif text.substr(i, 2) == "\\]": - text = text.substr(0, i) + "!" + text.substr(i + 2) - escaped_close_brackets.append(i) - - # Extract all of the BB codes so that we know the actual text (we could do this easier with - # a RichTextLabel but then we'd need to await idle_frame which is annoying) - var bbcode_positions = find_bbcode_positions_in_string(text) - var accumulaive_length_offset = 0 - for position in bbcode_positions: - # Ignore our own markers - if position.code in ["wait", "speed", "/speed", "do", "do!", "set", "next", "if", "else", "/if"]: - continue - - bbcodes.append({ - bbcode = position.bbcode, - start = position.start, - offset_start = position.start - accumulaive_length_offset - }) - accumulaive_length_offset += position.bbcode.length() - - for bb in bbcodes: - text = text.substr(0, bb.offset_start) + text.substr(bb.offset_start + bb.bbcode.length()) - - # Now find any dialogue markers - var next_bbcode_position = find_bbcode_positions_in_string(text, false) - var limit = 0 - while next_bbcode_position.size() > 0 and limit < 1000: - limit += 1 - - var bbcode = next_bbcode_position[0] - - var index = bbcode.start - var code = bbcode.code - var raw_args = bbcode.raw_args - var args = {} - if code in ["do", "do!", "set"]: - args["value"] = extract_mutation("%s %s" % [code, raw_args]) - else: - # Could be something like: - # "=1.0" - # " rate=20 level=10" - if raw_args and raw_args[0] == "=": - raw_args = "value" + raw_args - for pair in raw_args.strip_edges().split(" "): - if "=" in pair: - var bits = pair.split("=") - args[bits[0]] = bits[1] - - match code: - "wait": - if pauses.has(index): - pauses[index] += args.get("value").to_float() - else: - pauses[index] = args.get("value").to_float() - "speed": - speeds[index] = args.get("value").to_float() - "/speed": - speeds[index] = 1.0 - "do", "do!", "set": - mutations.append([index, args.get("value")]) - "next": - time = args.get("value") if args.has("value") else "0" - - # Find any BB codes that are after this index and remove the length from their start - var length = bbcode.bbcode.length() - for bb in bbcodes: - if bb.offset_start > bbcode.start: - bb.offset_start -= length - bb.start -= length - - # Find any escaped brackets after this that need moving - for i in range(0, escaped_open_brackets.size()): - if escaped_open_brackets[i] > bbcode.start: - escaped_open_brackets[i] -= length - for i in range(0, escaped_close_brackets.size()): - if escaped_close_brackets[i] > bbcode.start: - escaped_close_brackets[i] -= length - - text = text.substr(0, index) + text.substr(index + length) - next_bbcode_position = find_bbcode_positions_in_string(text, false) - - # Put the BB Codes back in - for bb in bbcodes: - text = text.insert(bb.start, bb.bbcode) - - # Put the escaped brackets back in - for index in escaped_open_brackets: - text = text.left(index) + "[" + text.right(text.length() - index - 1) - for index in escaped_close_brackets: - text = text.left(index) + "]" + text.right(text.length() - index - 1) - - return ResolvedLineData.new({ - text = text, - pauses = pauses, - speeds = speeds, - mutations = mutations, - time = time - }) - - -func find_bbcode_positions_in_string(string: String, find_all: bool = true) -> Array[Dictionary]: - if not "[" in string: return [] - - var positions: Array[Dictionary] = [] - - var open_brace_count: int = 0 - var start: int = 0 - var bbcode: String = "" - var code: String = "" - var is_finished_code: bool = false - for i in range(0, string.length()): - if string[i] == "[": - if open_brace_count == 0: - start = i - bbcode = "" - code = "" - is_finished_code = false - open_brace_count += 1 - - else: - if not is_finished_code and (string[i].to_upper() != string[i] or string[i] == "/" or string[i] == "!"): - code += string[i] - else: - is_finished_code = true - - if open_brace_count > 0: - bbcode += string[i] - - if string[i] == "]": - open_brace_count -= 1 - if open_brace_count == 0 and not code in ["if", "else", "/if"]: - positions.append({ - bbcode = bbcode, - code = code, - start = start, - raw_args = bbcode.substr(code.length() + 1, bbcode.length() - code.length() - 2).strip_edges() - }) - - if not find_all: - return positions - - return positions - - -func tokenise(text: String, line_type: String, index: int) -> Array: - var tokens: Array[Dictionary] = [] - var limit: int = 0 - while text.strip_edges() != "" and limit < 1000: - limit += 1 - var found = find_match(text) - if found.size() > 0: - tokens.append({ - index = index, - type = found.type, - value = found.value - }) - index += found.value.length() - text = found.remaining_text - elif text.begins_with(" "): - index += 1 - text = text.substr(1) - else: - return build_token_tree_error(DialogueConstants.ERR_INVALID_EXPRESSION, index) - - return build_token_tree(tokens, line_type, "")[0] - - -func build_token_tree_error(error: int, index: int) -> Array: - return [{ type = DialogueConstants.TOKEN_ERROR, value = error, index = index }] - - -func build_token_tree(tokens: Array[Dictionary], line_type: String, expected_close_token: String) -> Array: - var tree: Array[Dictionary] = [] - var limit = 0 - while tokens.size() > 0 and limit < 1000: - limit += 1 - var token = tokens.pop_front() - - var error = check_next_token(token, tokens, line_type, expected_close_token) - if error != OK: - return [build_token_tree_error(error, token.index), tokens] - - match token.type: - DialogueConstants.TOKEN_FUNCTION: - var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_PARENS_CLOSE) - - if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: - return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] - - tree.append({ - type = DialogueConstants.TOKEN_FUNCTION, - # Consume the trailing "(" - function = token.value.substr(0, token.value.length() - 1), - value = tokens_to_list(sub_tree[0]) - }) - tokens = sub_tree[1] - - DialogueConstants.TOKEN_DICTIONARY_REFERENCE: - var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACKET_CLOSE) - - if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: - return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] - - var args = tokens_to_list(sub_tree[0]) - if args.size() != 1: - return [build_token_tree_error(DialogueConstants.ERR_INVALID_INDEX, token.index), tokens] - - tree.append({ - type = DialogueConstants.TOKEN_DICTIONARY_REFERENCE, - # Consume the trailing "[" - variable = token.value.substr(0, token.value.length() - 1), - value = args[0] - }) - tokens = sub_tree[1] - - DialogueConstants.TOKEN_BRACE_OPEN: - var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACE_CLOSE) - - if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: - return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] - - var t = sub_tree[0] - for i in range(0, t.size() - 2): - # Convert Lua style dictionaries to string keys - if t[i].type == DialogueConstants.TOKEN_VARIABLE and t[i+1].type == DialogueConstants.TOKEN_ASSIGNMENT: - t[i].type = DialogueConstants.TOKEN_STRING - t[i+1].type = DialogueConstants.TOKEN_COLON - t[i+1].erase("value") - - tree.append({ - type = DialogueConstants.TOKEN_DICTIONARY, - value = tokens_to_dictionary(sub_tree[0]) - }) - - tokens = sub_tree[1] - - DialogueConstants.TOKEN_BRACKET_OPEN: - var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_BRACKET_CLOSE) - - if sub_tree[0].size() > 0 and sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: - return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] - - var type = DialogueConstants.TOKEN_ARRAY - var value = tokens_to_list(sub_tree[0]) - - # See if this is referencing a nested dictionary value - if tree.size() > 0: - var previous_token = tree[tree.size() - 1] - if previous_token.type in [DialogueConstants.TOKEN_DICTIONARY_REFERENCE, DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE]: - type = DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE - value = value[0] - - tree.append({ - type = type, - value = value - }) - tokens = sub_tree[1] - - DialogueConstants.TOKEN_PARENS_OPEN: - var sub_tree = build_token_tree(tokens, line_type, DialogueConstants.TOKEN_PARENS_CLOSE) - - if sub_tree[0][0].type == DialogueConstants.TOKEN_ERROR: - return [build_token_tree_error(sub_tree[0][0].value, token.index), tokens] - - tree.append({ - type = DialogueConstants.TOKEN_GROUP, - value = sub_tree[0] - }) - tokens = sub_tree[1] - - DialogueConstants.TOKEN_PARENS_CLOSE, \ - DialogueConstants.TOKEN_BRACE_CLOSE, \ - DialogueConstants.TOKEN_BRACKET_CLOSE: - if token.type != expected_close_token: - return [build_token_tree_error(DialogueConstants.ERR_UNEXPECTED_CLOSING_BRACKET, token.index), tokens] - - return [tree, tokens] - - DialogueConstants.TOKEN_NOT: - # Double nots negate each other - if tokens.size() > 0 and tokens.front().type == DialogueConstants.TOKEN_NOT: - tokens.pop_front() - else: - tree.append({ - type = token.type - }) - - DialogueConstants.TOKEN_COMMA, \ - DialogueConstants.TOKEN_COLON, \ - DialogueConstants.TOKEN_DOT: - tree.append({ - type = token.type - }) - - DialogueConstants.TOKEN_COMPARISON, \ - DialogueConstants.TOKEN_ASSIGNMENT, \ - DialogueConstants.TOKEN_OPERATOR, \ - DialogueConstants.TOKEN_AND_OR, \ - DialogueConstants.TOKEN_VARIABLE: \ - tree.append({ - type = token.type, - value = token.value.strip_edges() - }) - - DialogueConstants.TOKEN_STRING: - tree.append({ - type = token.type, - value = token.value.substr(1, token.value.length() - 2) - }) - - DialogueConstants.TOKEN_CONDITION: - return [build_token_tree_error(DialogueConstants.ERR_UNEXPECTED_CONDITION, token.index), token] - - DialogueConstants.TOKEN_BOOL: - tree.append({ - type = token.type, - value = token.value.to_lower() == "true" - }) - - DialogueConstants.TOKEN_NUMBER: - var value = token.value.to_float() if "." in token.value else token.value.to_int() - # If previous token is a number and this one is a negative number then - # inject a minus operator token in between them. - if tree.size() > 0 and token.value.begins_with("-") and tree[tree.size() - 1].type == DialogueConstants.TOKEN_NUMBER: - tree.append(({ - type = DialogueConstants.TOKEN_OPERATOR, - value = "-" - })) - tree.append({ - type = token.type, - value = -1 * value - }) - else: - tree.append({ - type = token.type, - value = value - }) - - if expected_close_token != "": - var index: int = tokens[0].index if tokens.size() > 0 else 0 - return [build_token_tree_error(DialogueConstants.ERR_MISSING_CLOSING_BRACKET, index), tokens] - - return [tree, tokens] - - -func check_next_token(token: Dictionary, next_tokens: Array[Dictionary], line_type: String, expected_close_token: String) -> Error: - var next_token: Dictionary = { type = null } - if next_tokens.size() > 0: - next_token = next_tokens.front() - - # Guard for assigning in a condition. If the assignment token isn't inside a Lua dictionary - # then it's an unexpected assignment in a condition line. - if token.type == DialogueConstants.TOKEN_ASSIGNMENT and line_type == DialogueConstants.TYPE_CONDITION and not next_tokens.any(func(t): return t.type == expected_close_token): - return DialogueConstants.ERR_UNEXPECTED_ASSIGNMENT - - # Special case for a negative number after this one - if token.type == DialogueConstants.TOKEN_NUMBER and next_token.type == DialogueConstants.TOKEN_NUMBER and next_token.value.begins_with("-"): - return OK - - var expected_token_types = [] - var unexpected_token_types = [] - match token.type: - DialogueConstants.TOKEN_FUNCTION, \ - DialogueConstants.TOKEN_PARENS_OPEN: - unexpected_token_types = [ - null, - DialogueConstants.TOKEN_COMMA, - DialogueConstants.TOKEN_COLON, - DialogueConstants.TOKEN_COMPARISON, - DialogueConstants.TOKEN_ASSIGNMENT, - DialogueConstants.TOKEN_OPERATOR, - DialogueConstants.TOKEN_AND_OR, - DialogueConstants.TOKEN_DOT - ] - - DialogueConstants.TOKEN_BRACKET_CLOSE: - unexpected_token_types = [ - DialogueConstants.TOKEN_NOT, - DialogueConstants.TOKEN_BOOL, - DialogueConstants.TOKEN_STRING, - DialogueConstants.TOKEN_NUMBER, - DialogueConstants.TOKEN_VARIABLE - ] - - DialogueConstants.TOKEN_BRACE_OPEN: - expected_token_types = [ - DialogueConstants.TOKEN_STRING, - DialogueConstants.TOKEN_VARIABLE, - DialogueConstants.TOKEN_NUMBER, - DialogueConstants.TOKEN_BRACE_CLOSE - ] - - DialogueConstants.TOKEN_PARENS_CLOSE, \ - DialogueConstants.TOKEN_BRACE_CLOSE: - unexpected_token_types = [ - DialogueConstants.TOKEN_NOT, - DialogueConstants.TOKEN_ASSIGNMENT, - DialogueConstants.TOKEN_BOOL, - DialogueConstants.TOKEN_STRING, - DialogueConstants.TOKEN_NUMBER, - DialogueConstants.TOKEN_VARIABLE - ] - - DialogueConstants.TOKEN_COMPARISON, \ - DialogueConstants.TOKEN_OPERATOR, \ - DialogueConstants.TOKEN_COMMA, \ - DialogueConstants.TOKEN_DOT, \ - DialogueConstants.TOKEN_NOT, \ - DialogueConstants.TOKEN_AND_OR, \ - DialogueConstants.TOKEN_DICTIONARY_REFERENCE: - unexpected_token_types = [ - null, - DialogueConstants.TOKEN_COMMA, - DialogueConstants.TOKEN_COLON, - DialogueConstants.TOKEN_COMPARISON, - DialogueConstants.TOKEN_ASSIGNMENT, - DialogueConstants.TOKEN_OPERATOR, - DialogueConstants.TOKEN_AND_OR, - DialogueConstants.TOKEN_PARENS_CLOSE, - DialogueConstants.TOKEN_BRACE_CLOSE, - DialogueConstants.TOKEN_BRACKET_CLOSE, - DialogueConstants.TOKEN_DOT - ] - - DialogueConstants.TOKEN_COLON: - unexpected_token_types = [ - DialogueConstants.TOKEN_COMMA, - DialogueConstants.TOKEN_COLON, - DialogueConstants.TOKEN_COMPARISON, - DialogueConstants.TOKEN_ASSIGNMENT, - DialogueConstants.TOKEN_OPERATOR, - DialogueConstants.TOKEN_AND_OR, - DialogueConstants.TOKEN_PARENS_CLOSE, - DialogueConstants.TOKEN_BRACE_CLOSE, - DialogueConstants.TOKEN_BRACKET_CLOSE, - DialogueConstants.TOKEN_DOT - ] - - DialogueConstants.TOKEN_BOOL, \ - DialogueConstants.TOKEN_STRING, \ - DialogueConstants.TOKEN_NUMBER: - unexpected_token_types = [ - DialogueConstants.TOKEN_NOT, - DialogueConstants.TOKEN_ASSIGNMENT, - DialogueConstants.TOKEN_BOOL, - DialogueConstants.TOKEN_STRING, - DialogueConstants.TOKEN_NUMBER, - DialogueConstants.TOKEN_VARIABLE, - DialogueConstants.TOKEN_FUNCTION, - DialogueConstants.TOKEN_PARENS_OPEN, - DialogueConstants.TOKEN_BRACE_OPEN, - DialogueConstants.TOKEN_BRACKET_OPEN - ] - - DialogueConstants.TOKEN_VARIABLE: - unexpected_token_types = [ - DialogueConstants.TOKEN_NOT, - DialogueConstants.TOKEN_BOOL, - DialogueConstants.TOKEN_STRING, - DialogueConstants.TOKEN_NUMBER, - DialogueConstants.TOKEN_VARIABLE, - DialogueConstants.TOKEN_FUNCTION, - DialogueConstants.TOKEN_PARENS_OPEN, - DialogueConstants.TOKEN_BRACE_OPEN, - DialogueConstants.TOKEN_BRACKET_OPEN - ] - - if (expected_token_types.size() > 0 and not next_token.type in expected_token_types or unexpected_token_types.size() > 0 and next_token.type in unexpected_token_types): - match next_token.type: - null: - return DialogueConstants.ERR_UNEXPECTED_END_OF_EXPRESSION - - DialogueConstants.TOKEN_FUNCTION: - return DialogueConstants.ERR_UNEXPECTED_FUNCTION - - DialogueConstants.TOKEN_PARENS_OPEN, \ - DialogueConstants.TOKEN_PARENS_CLOSE: - return DialogueConstants.ERR_UNEXPECTED_BRACKET - - DialogueConstants.TOKEN_COMPARISON, \ - DialogueConstants.TOKEN_ASSIGNMENT, \ - DialogueConstants.TOKEN_OPERATOR, \ - DialogueConstants.TOKEN_NOT, \ - DialogueConstants.TOKEN_AND_OR: - return DialogueConstants.ERR_UNEXPECTED_OPERATOR - - DialogueConstants.TOKEN_COMMA: - return DialogueConstants.ERR_UNEXPECTED_COMMA - DialogueConstants.TOKEN_COLON: - return DialogueConstants.ERR_UNEXPECTED_COLON - DialogueConstants.TOKEN_DOT: - return DialogueConstants.ERR_UNEXPECTED_DOT - - DialogueConstants.TOKEN_BOOL: - return DialogueConstants.ERR_UNEXPECTED_BOOLEAN - DialogueConstants.TOKEN_STRING: - return DialogueConstants.ERR_UNEXPECTED_STRING - DialogueConstants.TOKEN_NUMBER: - return DialogueConstants.ERR_UNEXPECTED_NUMBER - DialogueConstants.TOKEN_VARIABLE: - return DialogueConstants.ERR_UNEXPECTED_VARIABLE - - return DialogueConstants.ERR_INVALID_EXPRESSION - - return OK - - -func tokens_to_list(tokens: Array[Dictionary]) -> Array[Array]: - var list: Array[Array] = [] - var current_item: Array[Dictionary] = [] - for token in tokens: - if token.type == DialogueConstants.TOKEN_COMMA: - list.append(current_item) - current_item = [] - else: - current_item.append(token) - - if current_item.size() > 0: - list.append(current_item) - - return list - - -func tokens_to_dictionary(tokens: Array[Dictionary]) -> Dictionary: - var dictionary = {} - for i in range(0, tokens.size()): - if tokens[i].type == DialogueConstants.TOKEN_COLON: - if tokens.size() == i + 2: - dictionary[tokens[i-1]] = tokens[i+1] - else: - dictionary[tokens[i-1]] = { type = DialogueConstants.TOKEN_GROUP, value = tokens.slice(i+1) } - - return dictionary - - -func find_match(input: String) -> Dictionary: - for key in TOKEN_DEFINITIONS.keys(): - var regex = TOKEN_DEFINITIONS.get(key) - var found = regex.search(input) - if found: - return { - type = key, - remaining_text = input.substr(found.strings[0].length()), - value = found.strings[0] - } - - return {} diff --git a/addons/dialogue_manager/components/resolved_line_data.gd b/addons/dialogue_manager/components/resolved_line_data.gd deleted file mode 100644 index 1073586..0000000 --- a/addons/dialogue_manager/components/resolved_line_data.gd +++ /dev/null @@ -1,15 +0,0 @@ -extends RefCounted - -var text: String = "" -var pauses: Dictionary = {} -var speeds: Dictionary = {} -var mutations: Array[Array] = [] -var time: String = "" - - -func _init(data: Dictionary) -> void: - text = data.text - pauses = data.pauses - speeds = data.speeds - mutations = data.mutations - time = data.time diff --git a/addons/dialogue_manager/components/resolved_tag_data.gd b/addons/dialogue_manager/components/resolved_tag_data.gd deleted file mode 100644 index 728cc42..0000000 --- a/addons/dialogue_manager/components/resolved_tag_data.gd +++ /dev/null @@ -1,10 +0,0 @@ -extends RefCounted - - -var tags: PackedStringArray = [] -var line_without_tags: String = "" - - -func _init(data: Dictionary) -> void: - tags = data.tags - line_without_tags = data.line_without_tags diff --git a/addons/dialogue_manager/components/search_and_replace.gd b/addons/dialogue_manager/components/search_and_replace.gd deleted file mode 100644 index c47ac5b..0000000 --- a/addons/dialogue_manager/components/search_and_replace.gd +++ /dev/null @@ -1,210 +0,0 @@ -@tool -extends VBoxContainer - - -signal open_requested() -signal close_requested() - - -const DialogueConstants = preload("../constants.gd") - - -@onready var input: LineEdit = $Search/Input -@onready var result_label: Label = $Search/ResultLabel -@onready var previous_button: Button = $Search/PreviousButton -@onready var next_button: Button = $Search/NextButton -@onready var match_case_button: CheckBox = $Search/MatchCaseCheckBox -@onready var replace_check_button: CheckButton = $Search/ReplaceCheckButton -@onready var replace_panel: HBoxContainer = $Replace -@onready var replace_input: LineEdit = $Replace/Input -@onready var replace_button: Button = $Replace/ReplaceButton -@onready var replace_all_button: Button = $Replace/ReplaceAllButton - -# The code edit we will be affecting (for some reason exporting this didn't work) -var code_edit: CodeEdit: - set(next_code_edit): - code_edit = next_code_edit - code_edit.gui_input.connect(_on_text_edit_gui_input) - code_edit.text_changed.connect(_on_text_edit_text_changed) - get: - return code_edit - -var results: Array = [] -var result_index: int = -1: - set(next_result_index): - result_index = next_result_index - if results.size() > 0: - var r = results[result_index] - code_edit.set_caret_line(r[0]) - code_edit.select(r[0], r[1], r[0], r[1] + r[2]) - else: - result_index = -1 - if is_instance_valid(code_edit): - code_edit.deselect() - - result_label.text = DialogueConstants.translate(&"n_of_n").format({ index = result_index + 1, total = results.size() }) - get: - return result_index - - -func _ready() -> void: - apply_theme() - - input.placeholder_text = DialogueConstants.translate(&"search.placeholder") - previous_button.tooltip_text = DialogueConstants.translate(&"search.previous") - next_button.tooltip_text = DialogueConstants.translate(&"search.next") - match_case_button.text = DialogueConstants.translate(&"search.match_case") - $Search/ReplaceCheckButton.text = DialogueConstants.translate(&"search.toggle_replace") - replace_button.text = DialogueConstants.translate(&"search.replace") - replace_all_button.text = DialogueConstants.translate(&"search.replace_all") - $Replace/ReplaceLabel.text = DialogueConstants.translate(&"search.replace_with") - - self.result_index = -1 - - replace_panel.hide() - replace_button.disabled = true - replace_all_button.disabled = true - - hide() - - -func focus_line_edit() -> void: - input.grab_focus() - input.select_all() - - -func apply_theme() -> void: - if is_instance_valid(previous_button): - previous_button.icon = get_theme_icon("ArrowLeft", "EditorIcons") - if is_instance_valid(next_button): - next_button.icon = get_theme_icon("ArrowRight", "EditorIcons") - - -# Find text in the code -func search(text: String = "", default_result_index: int = 0) -> void: - results.clear() - - if text == "": - text = input.text - - var lines = code_edit.text.split("\n") - for line_number in range(0, lines.size()): - var line = lines[line_number] - - var column = find_in_line(line, text, 0) - while column > -1: - results.append([line_number, column, text.length()]) - column = find_in_line(line, text, column + 1) - - if results.size() > 0: - replace_button.disabled = false - replace_all_button.disabled = false - else: - replace_button.disabled = true - replace_all_button.disabled = true - - self.result_index = clamp(default_result_index, 0, results.size() - 1) - - -# Find text in a string and match case if requested -func find_in_line(line: String, text: String, from_index: int = 0) -> int: - if match_case_button.button_pressed: - return line.find(text, from_index) - else: - return line.findn(text, from_index) - - -### Signals - - -func _on_text_edit_gui_input(event: InputEvent) -> void: - if event is InputEventKey and event.is_pressed(): - match event.as_text(): - "Ctrl+F", "Command+F": - open_requested.emit() - "Ctrl+Shift+R", "Command+Shift+R": - replace_check_button.set_pressed(true) - open_requested.emit() - - -func _on_text_edit_text_changed() -> void: - results.clear() - - -func _on_search_and_replace_theme_changed() -> void: - apply_theme() - - -func _on_input_text_changed(new_text: String) -> void: - search(new_text) - - -func _on_previous_button_pressed() -> void: - self.result_index = wrapi(result_index - 1, 0, results.size()) - - -func _on_next_button_pressed() -> void: - self.result_index = wrapi(result_index + 1, 0, results.size()) - - -func _on_search_and_replace_visibility_changed() -> void: - if is_instance_valid(input): - if visible: - input.grab_focus() - var selection = code_edit.get_selected_text() - if input.text == "" and selection != "": - input.text = selection - search(selection) - else: - search() - else: - input.text = "" - - -func _on_input_gui_input(event: InputEvent) -> void: - if event is InputEventKey and event.is_pressed(): - match event.as_text(): - "Enter": - search(input.text) - "Escape": - emit_signal("close_requested") - - -func _on_replace_button_pressed() -> void: - if result_index == -1: return - - # Replace the selection at result index - var r: Array = results[result_index] - var lines: PackedStringArray = code_edit.text.split("\n") - var line: String = lines[r[0]] - line = line.substr(0, r[1]) + replace_input.text + line.substr(r[1] + r[2]) - lines[r[0]] = line - code_edit.text = "\n".join(lines) - search(input.text, result_index) - code_edit.text_changed.emit() - - -func _on_replace_all_button_pressed() -> void: - if match_case_button.button_pressed: - code_edit.text = code_edit.text.replace(input.text, replace_input.text) - else: - code_edit.text = code_edit.text.replacen(input.text, replace_input.text) - search() - code_edit.text_changed.emit() - - -func _on_replace_check_button_toggled(button_pressed: bool) -> void: - replace_panel.visible = button_pressed - if button_pressed: - replace_input.grab_focus() - - -func _on_input_focus_entered() -> void: - if results.size() == 0: - search() - else: - self.result_index = result_index - - -func _on_match_case_check_box_toggled(button_pressed: bool) -> void: - search() diff --git a/addons/dialogue_manager/components/search_and_replace.tscn b/addons/dialogue_manager/components/search_and_replace.tscn deleted file mode 100644 index 82dd60d..0000000 --- a/addons/dialogue_manager/components/search_and_replace.tscn +++ /dev/null @@ -1,87 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://gr8nakpbrhby"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/search_and_replace.gd" id="1_8oj1f"] - -[node name="SearchAndReplace" type="VBoxContainer"] -visible = false -anchors_preset = 10 -anchor_right = 1.0 -offset_bottom = 31.0 -grow_horizontal = 2 -size_flags_horizontal = 3 -script = ExtResource("1_8oj1f") - -[node name="Search" type="HBoxContainer" parent="."] -layout_mode = 2 - -[node name="Input" type="LineEdit" parent="Search"] -layout_mode = 2 -size_flags_horizontal = 3 -placeholder_text = "Text to search for" -metadata/_edit_use_custom_anchors = true - -[node name="MatchCaseCheckBox" type="CheckBox" parent="Search"] -layout_mode = 2 -text = "Match case" - -[node name="VSeparator" type="VSeparator" parent="Search"] -layout_mode = 2 - -[node name="PreviousButton" type="Button" parent="Search"] -layout_mode = 2 -tooltip_text = "Previous" -flat = true - -[node name="ResultLabel" type="Label" parent="Search"] -layout_mode = 2 -text = "0 of 0" - -[node name="NextButton" type="Button" parent="Search"] -layout_mode = 2 -tooltip_text = "Next" -flat = true - -[node name="VSeparator2" type="VSeparator" parent="Search"] -layout_mode = 2 - -[node name="ReplaceCheckButton" type="CheckButton" parent="Search"] -layout_mode = 2 -text = "Replace" - -[node name="Replace" type="HBoxContainer" parent="."] -visible = false -layout_mode = 2 - -[node name="ReplaceLabel" type="Label" parent="Replace"] -layout_mode = 2 -text = "Replace with:" - -[node name="Input" type="LineEdit" parent="Replace"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="ReplaceButton" type="Button" parent="Replace"] -layout_mode = 2 -disabled = true -text = "Replace" -flat = true - -[node name="ReplaceAllButton" type="Button" parent="Replace"] -layout_mode = 2 -disabled = true -text = "Replace all" -flat = true - -[connection signal="theme_changed" from="." to="." method="_on_search_and_replace_theme_changed"] -[connection signal="visibility_changed" from="." to="." method="_on_search_and_replace_visibility_changed"] -[connection signal="focus_entered" from="Search/Input" to="." method="_on_input_focus_entered"] -[connection signal="gui_input" from="Search/Input" to="." method="_on_input_gui_input"] -[connection signal="text_changed" from="Search/Input" to="." method="_on_input_text_changed"] -[connection signal="toggled" from="Search/MatchCaseCheckBox" to="." method="_on_match_case_check_box_toggled"] -[connection signal="pressed" from="Search/PreviousButton" to="." method="_on_previous_button_pressed"] -[connection signal="pressed" from="Search/NextButton" to="." method="_on_next_button_pressed"] -[connection signal="toggled" from="Search/ReplaceCheckButton" to="." method="_on_replace_check_button_toggled"] -[connection signal="focus_entered" from="Replace/Input" to="." method="_on_input_focus_entered"] -[connection signal="gui_input" from="Replace/Input" to="." method="_on_input_gui_input"] -[connection signal="pressed" from="Replace/ReplaceButton" to="." method="_on_replace_button_pressed"] -[connection signal="pressed" from="Replace/ReplaceAllButton" to="." method="_on_replace_all_button_pressed"] diff --git a/addons/dialogue_manager/components/title_list.gd b/addons/dialogue_manager/components/title_list.gd deleted file mode 100644 index ee7cd13..0000000 --- a/addons/dialogue_manager/components/title_list.gd +++ /dev/null @@ -1,67 +0,0 @@ -@tool -extends VBoxContainer - -signal title_selected(title: String) - - -const DialogueConstants = preload("../constants.gd") - - -@onready var filter_edit: LineEdit = $FilterEdit -@onready var list: ItemList = $List - -var titles: PackedStringArray: - set(next_titles): - titles = next_titles - apply_filter() - get: - return titles - -var filter: String: - set(next_filter): - filter = next_filter - apply_filter() - get: - return filter - - -func _ready() -> void: - apply_theme() - - filter_edit.placeholder_text = DialogueConstants.translate(&"titles_list.filter") - - -func select_title(title: String) -> void: - list.deselect_all() - for i in range(0, list.get_item_count()): - if list.get_item_text(i) == title.strip_edges(): - list.select(i) - - -func apply_filter() -> void: - list.clear() - for title in titles: - if filter == "" or filter.to_lower() in title.to_lower(): - list.add_item(title.strip_edges()) - - -func apply_theme() -> void: - if is_instance_valid(filter_edit): - filter_edit.right_icon = get_theme_icon("Search", "EditorIcons") - - -### Signals - - -func _on_theme_changed() -> void: - apply_theme() - - -func _on_filter_edit_text_changed(new_text: String) -> void: - self.filter = new_text - - -func _on_list_item_clicked(index: int, at_position: Vector2, mouse_button_index: int) -> void: - if mouse_button_index == MOUSE_BUTTON_LEFT: - var title = list.get_item_text(index) - title_selected.emit(title) diff --git a/addons/dialogue_manager/components/title_list.tscn b/addons/dialogue_manager/components/title_list.tscn deleted file mode 100644 index 3e5c9a0..0000000 --- a/addons/dialogue_manager/components/title_list.tscn +++ /dev/null @@ -1,45 +0,0 @@ -[gd_scene load_steps=4 format=3 uid="uid://ctns6ouwwd68i"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/title_list.gd" id="1_5qqmd"] - -[sub_resource type="Image" id="Image_o5dqs"] -data = { -"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), -"format": "RGBA8", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_ekmpw"] -image = SubResource("Image_o5dqs") - -[node name="TitleList" type="VBoxContainer"] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -script = ExtResource("1_5qqmd") - -[node name="FilterEdit" type="LineEdit" parent="."] -layout_mode = 2 -offset_right = 1152.0 -offset_bottom = 31.0 -placeholder_text = "Filter titles" -clear_button_enabled = true -right_icon = SubResource("ImageTexture_ekmpw") - -[node name="List" type="ItemList" parent="."] -layout_mode = 2 -offset_top = 35.0 -offset_right = 1152.0 -offset_bottom = 648.0 -size_flags_vertical = 3 -allow_reselect = true - -[connection signal="theme_changed" from="." to="." method="_on_theme_changed"] -[connection signal="text_changed" from="FilterEdit" to="." method="_on_filter_edit_text_changed"] -[connection signal="item_clicked" from="List" to="." method="_on_list_item_clicked"] diff --git a/addons/dialogue_manager/components/update_button.gd b/addons/dialogue_manager/components/update_button.gd deleted file mode 100644 index b8c2809..0000000 --- a/addons/dialogue_manager/components/update_button.gd +++ /dev/null @@ -1,126 +0,0 @@ -@tool -extends Button - -const DialogueConstants = preload("../constants.gd") -const DialogueSettings = preload("../settings.gd") - -const REMOTE_RELEASES_URL = "https://api.github.com/repos/nathanhoad/godot_dialogue_manager/releases" - - -@onready var http_request: HTTPRequest = $HTTPRequest -@onready var download_dialog: AcceptDialog = $DownloadDialog -@onready var download_update_panel = $DownloadDialog/DownloadUpdatePanel -@onready var needs_reload_dialog: AcceptDialog = $NeedsReloadDialog -@onready var update_failed_dialog: AcceptDialog = $UpdateFailedDialog -@onready var timer: Timer = $Timer - -# The main editor plugin -var editor_plugin: EditorPlugin - -var needs_reload: bool = false - -# A lambda that gets called just before refreshing the plugin. Return false to stop the reload. -var on_before_refresh: Callable = func(): return true - - -func _ready() -> void: - hide() - apply_theme() - - # Check for updates on GitHub - check_for_update() - - # Check again every few hours - timer.start(60 * 60 * 12) - - -# Convert a version number to an actually comparable number -func version_to_number(version: String) -> int: - var bits = version.split(".") - return bits[0].to_int() * 1000000 + bits[1].to_int() * 1000 + bits[2].to_int() - - -func apply_theme() -> void: - var color: Color = get_theme_color("success_color", "Editor") - - if needs_reload: - color = get_theme_color("error_color", "Editor") - icon = get_theme_icon("Reload", "EditorIcons") - add_theme_color_override("icon_normal_color", color) - add_theme_color_override("icon_focus_color", color) - add_theme_color_override("icon_hover_color", color) - - add_theme_color_override("font_color", color) - add_theme_color_override("font_focus_color", color) - add_theme_color_override("font_hover_color", color) - - -func check_for_update() -> void: - if DialogueSettings.get_user_value("check_for_updates", true): - http_request.request(REMOTE_RELEASES_URL) - - -### Signals - - -func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void: - if result != HTTPRequest.RESULT_SUCCESS: return - - var current_version: String = editor_plugin.get_version() - - # Work out the next version from the releases information on GitHub - var response = JSON.parse_string(body.get_string_from_utf8()) - if typeof(response) != TYPE_ARRAY: return - - # GitHub releases are in order of creation, not order of version - var versions = (response as Array).filter(func(release): - var version: String = release.tag_name.substr(1) - return version_to_number(version) > version_to_number(current_version) - ) - if versions.size() > 0: - download_update_panel.next_version_release = versions[0] - text = DialogueConstants.translate(&"update.available").format({ version = versions[0].tag_name.substr(1) }) - show() - - -func _on_update_button_pressed() -> void: - if needs_reload: - var will_refresh = on_before_refresh.call() - if will_refresh: - editor_plugin.get_editor_interface().restart_editor(true) - else: - var scale: float = editor_plugin.get_editor_interface().get_editor_scale() - download_dialog.min_size = Vector2(300, 250) * scale - download_dialog.popup_centered() - - -func _on_download_dialog_close_requested() -> void: - download_dialog.hide() - - -func _on_download_update_panel_updated(updated_to_version: String) -> void: - download_dialog.hide() - - needs_reload_dialog.dialog_text = DialogueConstants.translate(&"update.needs_reload") - needs_reload_dialog.ok_button_text = DialogueConstants.translate(&"update.reload_ok_button") - needs_reload_dialog.cancel_button_text = DialogueConstants.translate(&"update.reload_cancel_button") - needs_reload_dialog.popup_centered() - - needs_reload = true - text = DialogueConstants.translate(&"update.reload_project") - apply_theme() - - -func _on_download_update_panel_failed() -> void: - download_dialog.hide() - update_failed_dialog.dialog_text = DialogueConstants.translate(&"update.failed") - update_failed_dialog.popup_centered() - - -func _on_needs_reload_dialog_confirmed() -> void: - editor_plugin.get_editor_interface().restart_editor(true) - - -func _on_timer_timeout() -> void: - if not needs_reload: - check_for_update() diff --git a/addons/dialogue_manager/components/update_button.tscn b/addons/dialogue_manager/components/update_button.tscn deleted file mode 100644 index 533a94e..0000000 --- a/addons/dialogue_manager/components/update_button.tscn +++ /dev/null @@ -1,42 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://co8yl23idiwbi"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/components/update_button.gd" id="1_d2tpb"] -[ext_resource type="PackedScene" uid="uid://qdxrxv3c3hxk" path="res://addons/dialogue_manager/components/download_update_panel.tscn" id="2_iwm7r"] - -[node name="UpdateButton" type="Button"] -visible = false -offset_right = 8.0 -offset_bottom = 8.0 -theme_override_colors/font_color = Color(0, 0, 0, 1) -theme_override_colors/font_hover_color = Color(0, 0, 0, 1) -theme_override_colors/font_focus_color = Color(0, 0, 0, 1) -text = "v2.9.0 available" -flat = true -script = ExtResource("1_d2tpb") - -[node name="HTTPRequest" type="HTTPRequest" parent="."] - -[node name="DownloadDialog" type="AcceptDialog" parent="."] -title = "Download update" -size = Vector2i(400, 300) -unresizable = true -min_size = Vector2i(300, 250) -ok_button_text = "Close" - -[node name="DownloadUpdatePanel" parent="DownloadDialog" instance=ExtResource("2_iwm7r")] - -[node name="UpdateFailedDialog" type="AcceptDialog" parent="."] -dialog_text = "You have been updated to version 2.4.3" - -[node name="NeedsReloadDialog" type="ConfirmationDialog" parent="."] - -[node name="Timer" type="Timer" parent="."] -wait_time = 14400.0 - -[connection signal="pressed" from="." to="." method="_on_update_button_pressed"] -[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_request_completed"] -[connection signal="close_requested" from="DownloadDialog" to="." method="_on_download_dialog_close_requested"] -[connection signal="failed" from="DownloadDialog/DownloadUpdatePanel" to="." method="_on_download_update_panel_failed"] -[connection signal="updated" from="DownloadDialog/DownloadUpdatePanel" to="." method="_on_download_update_panel_updated"] -[connection signal="confirmed" from="NeedsReloadDialog" to="." method="_on_needs_reload_dialog_confirmed"] -[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"] diff --git a/addons/dialogue_manager/constants.gd b/addons/dialogue_manager/constants.gd deleted file mode 100644 index bc93d21..0000000 --- a/addons/dialogue_manager/constants.gd +++ /dev/null @@ -1,187 +0,0 @@ -extends Node - - -const USER_CONFIG_PATH = "user://dialogue_manager_user_config.json" -const CACHE_PATH = "user://dialogue_manager_cache.json" - -# Token types - -const TOKEN_FUNCTION = &"function" -const TOKEN_DICTIONARY_REFERENCE = &"dictionary_reference" -const TOKEN_DICTIONARY_NESTED_REFERENCE = &"dictionary_nested_reference" -const TOKEN_GROUP = &"group" -const TOKEN_ARRAY = &"array" -const TOKEN_DICTIONARY = &"dictionary" -const TOKEN_PARENS_OPEN = &"parens_open" -const TOKEN_PARENS_CLOSE = &"parens_close" -const TOKEN_BRACKET_OPEN = &"bracket_open" -const TOKEN_BRACKET_CLOSE = &"bracket_close" -const TOKEN_BRACE_OPEN = &"brace_open" -const TOKEN_BRACE_CLOSE = &"brace_close" -const TOKEN_COLON = &"colon" -const TOKEN_COMPARISON = &"comparison" -const TOKEN_ASSIGNMENT = &"assignment" -const TOKEN_OPERATOR = &"operator" -const TOKEN_COMMA = &"comma" -const TOKEN_DOT = &"dot" -const TOKEN_CONDITION = &"condition" -const TOKEN_BOOL = &"bool" -const TOKEN_NOT = &"not" -const TOKEN_AND_OR = &"and_or" -const TOKEN_STRING = &"string" -const TOKEN_NUMBER = &"number" -const TOKEN_VARIABLE = &"variable" -const TOKEN_COMMENT = &"comment" - -const TOKEN_ERROR = &"error" - -# Line types - -const TYPE_UNKNOWN = &"unknown" -const TYPE_RESPONSE = &"response" -const TYPE_TITLE = &"title" -const TYPE_CONDITION = &"condition" -const TYPE_MUTATION = &"mutation" -const TYPE_GOTO = &"goto" -const TYPE_DIALOGUE = &"dialogue" -const TYPE_ERROR = &"error" - -const TYPE_ELSE = &"else" - -# Line IDs - -const ID_NULL = &"" -const ID_ERROR = &"error" -const ID_ERROR_INVALID_TITLE = &"invalid title" -const ID_ERROR_TITLE_HAS_NO_BODY = &"title has no body" -const ID_END = &"end" -const ID_END_CONVERSATION = &"end!" - -# Errors - -const ERR_ERRORS_IN_IMPORTED_FILE = 100 -const ERR_FILE_ALREADY_IMPORTED = 101 -const ERR_DUPLICATE_IMPORT_NAME = 102 -const ERR_EMPTY_TITLE = 103 -const ERR_DUPLICATE_TITLE = 104 -const ERR_NESTED_TITLE = 105 -const ERR_TITLE_INVALID_CHARACTERS = 106 -const ERR_UNKNOWN_TITLE = 107 -const ERR_INVALID_TITLE_REFERENCE = 108 -const ERR_TITLE_REFERENCE_HAS_NO_CONTENT = 109 -const ERR_INVALID_EXPRESSION = 110 -const ERR_UNEXPECTED_CONDITION = 111 -const ERR_DUPLICATE_ID = 112 -const ERR_MISSING_ID = 113 -const ERR_INVALID_INDENTATION = 114 -const ERR_INVALID_CONDITION_INDENTATION = 115 -const ERR_INCOMPLETE_EXPRESSION = 116 -const ERR_INVALID_EXPRESSION_FOR_VALUE = 117 -const ERR_UNKNOWN_LINE_SYNTAX = 118 -const ERR_TITLE_BEGINS_WITH_NUMBER = 119 -const ERR_UNEXPECTED_END_OF_EXPRESSION = 120 -const ERR_UNEXPECTED_FUNCTION = 121 -const ERR_UNEXPECTED_BRACKET = 122 -const ERR_UNEXPECTED_CLOSING_BRACKET = 123 -const ERR_MISSING_CLOSING_BRACKET = 124 -const ERR_UNEXPECTED_OPERATOR = 125 -const ERR_UNEXPECTED_COMMA = 126 -const ERR_UNEXPECTED_COLON = 127 -const ERR_UNEXPECTED_DOT = 128 -const ERR_UNEXPECTED_BOOLEAN = 129 -const ERR_UNEXPECTED_STRING = 130 -const ERR_UNEXPECTED_NUMBER = 131 -const ERR_UNEXPECTED_VARIABLE = 132 -const ERR_INVALID_INDEX = 133 -const ERR_UNEXPECTED_ASSIGNMENT = 134 -const ERR_UNKNOWN_USING = 135 - - -## Get the error message -static func get_error_message(error: int) -> String: - match error: - ERR_ERRORS_IN_IMPORTED_FILE: - return translate(&"errors.import_errors") - ERR_FILE_ALREADY_IMPORTED: - return translate(&"errors.already_imported") - ERR_DUPLICATE_IMPORT_NAME: - return translate(&"errors.duplicate_import") - ERR_EMPTY_TITLE: - return translate(&"errors.empty_title") - ERR_DUPLICATE_TITLE: - return translate(&"errors.duplicate_title") - ERR_NESTED_TITLE: - return translate(&"errors.nested_title") - ERR_TITLE_INVALID_CHARACTERS: - return translate(&"errors.invalid_title_string") - ERR_TITLE_BEGINS_WITH_NUMBER: - return translate(&"errors.invalid_title_number") - ERR_UNKNOWN_TITLE: - return translate(&"errors.unknown_title") - ERR_INVALID_TITLE_REFERENCE: - return translate(&"errors.jump_to_invalid_title") - ERR_TITLE_REFERENCE_HAS_NO_CONTENT: - return translate(&"errors.title_has_no_content") - ERR_INVALID_EXPRESSION: - return translate(&"errors.invalid_expression") - ERR_UNEXPECTED_CONDITION: - return translate(&"errors.unexpected_condition") - ERR_DUPLICATE_ID: - return translate(&"errors.duplicate_id") - ERR_MISSING_ID: - return translate(&"errors.missing_id") - ERR_INVALID_INDENTATION: - return translate(&"errors.invalid_indentation") - ERR_INVALID_CONDITION_INDENTATION: - return translate(&"errors.condition_has_no_content") - ERR_INCOMPLETE_EXPRESSION: - return translate(&"errors.incomplete_expression") - ERR_INVALID_EXPRESSION_FOR_VALUE: - return translate(&"errors.invalid_expression_for_value") - ERR_FILE_NOT_FOUND: - return translate(&"errors.file_not_found") - ERR_UNEXPECTED_END_OF_EXPRESSION: - return translate(&"errors.unexpected_end_of_expression") - ERR_UNEXPECTED_FUNCTION: - return translate(&"errors.unexpected_function") - ERR_UNEXPECTED_BRACKET: - return translate(&"errors.unexpected_bracket") - ERR_UNEXPECTED_CLOSING_BRACKET: - return translate(&"errors.unexpected_closing_bracket") - ERR_MISSING_CLOSING_BRACKET: - return translate(&"errors.missing_closing_bracket") - ERR_UNEXPECTED_OPERATOR: - return translate(&"errors.unexpected_operator") - ERR_UNEXPECTED_COMMA: - return translate(&"errors.unexpected_comma") - ERR_UNEXPECTED_COLON: - return translate(&"errors.unexpected_colon") - ERR_UNEXPECTED_DOT: - return translate(&"errors.unexpected_dot") - ERR_UNEXPECTED_BOOLEAN: - return translate(&"errors.unexpected_boolean") - ERR_UNEXPECTED_STRING: - return translate(&"errors.unexpected_string") - ERR_UNEXPECTED_NUMBER: - return translate(&"errors.unexpected_number") - ERR_UNEXPECTED_VARIABLE: - return translate(&"errors.unexpected_variable") - ERR_INVALID_INDEX: - return translate(&"errors.invalid_index") - ERR_UNEXPECTED_ASSIGNMENT: - return translate(&"errors.unexpected_assignment") - ERR_UNKNOWN_USING: - return translate(&"errors.unknown_using") - - return translate(&"errors.unknown") - - -static func translate(string: String) -> String: - var base_path = new().get_script().resource_path.get_base_dir() - - var language: String = TranslationServer.get_tool_locale() - var translations_path: String = "%s/l10n/%s.po" % [base_path, language] - var fallback_translations_path: String = "%s/l10n/%s.po" % [base_path, TranslationServer.get_tool_locale().substr(0, 2)] - var en_translations_path: String = "%s/l10n/en.po" % base_path - var translations: Translation = load(translations_path if FileAccess.file_exists(translations_path) else (fallback_translations_path if FileAccess.file_exists(fallback_translations_path) else en_translations_path)) - return translations.get_message(string) diff --git a/addons/dialogue_manager/dialogue_label.gd b/addons/dialogue_manager/dialogue_label.gd deleted file mode 100644 index 24057be..0000000 --- a/addons/dialogue_manager/dialogue_label.gd +++ /dev/null @@ -1,226 +0,0 @@ -@icon("./assets/icon.svg") - -@tool - -## A RichTextLabel specifically for use with [b]Dialogue Manager[/b] dialogue. -class_name DialogueLabel extends RichTextLabel - - -## Emitted for each letter typed out. -signal spoke(letter: String, letter_index: int, speed: float) - -## Emitted when typing paused for a `[wait]` -signal paused_typing(duration: float) - -## Emitted when the player skips the typing of dialogue. -signal skipped_typing() - -## Emitted when typing finishes. -signal finished_typing() - - -# The action to press to skip typing. -@export var skip_action: StringName = &"ui_cancel" - -## The speed with which the text types out. -@export var seconds_per_step: float = 0.02 - -## Automatically have a brief pause when these characters are encountered. -@export var pause_at_characters: String = ".?!" - -## Don't auto pause if the charcter after the pause is one of these. -@export var skip_pause_at_character_if_followed_by: String = ")\"" - -## Don't auto pause after these abbreviations (only if "." is in `pause_at_characters`).[br] -## Abbreviations are limitted to 5 characters in length [br] -## Does not support multi-period abbreviations (ex. "p.m.") -@export var skip_pause_at_abbreviations: PackedStringArray = ["Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex"] - -## The amount of time to pause when exposing a character present in pause_at_characters. -@export var seconds_per_pause_step: float = 0.3 - - -## The current line of dialogue. -var dialogue_line: - set(next_dialogue_line): - dialogue_line = next_dialogue_line - custom_minimum_size = Vector2.ZERO - text = dialogue_line.text - get: - return dialogue_line - -## Whether the label is currently typing itself out. -var is_typing: bool = false: - set(value): - var is_finished: bool = is_typing != value and value == false - is_typing = value - if is_finished: - finished_typing.emit() - get: - return is_typing - -var _last_wait_index: int = -1 -var _last_mutation_index: int = -1 -var _waiting_seconds: float = 0 -var _is_awaiting_mutation: bool = false - - -func _process(delta: float) -> void: - if self.is_typing: - # Type out text - if visible_ratio < 1: - # See if we are waiting - if _waiting_seconds > 0: - _waiting_seconds = _waiting_seconds - delta - # If we are no longer waiting then keep typing - if _waiting_seconds <= 0: - _type_next(delta, _waiting_seconds) - else: - # Make sure any mutations at the end of the line get run - _mutate_inline_mutations(get_total_character_count()) - self.is_typing = false - - -func _unhandled_input(event: InputEvent) -> void: - # Note: this will no longer be reached if using Dialogue Manager > 2.32.2. To make skip handling - # simpler (so all of mouse/keyboard/joypad are together) it is now the responsibility of the - # dialogue balloon. - if self.is_typing and visible_ratio < 1 and InputMap.has_action(skip_action) and event.is_action_pressed(skip_action): - get_viewport().set_input_as_handled() - skip_typing() - - -## Start typing out the text -func type_out() -> void: - text = dialogue_line.text - visible_characters = 0 - visible_ratio = 0 - _waiting_seconds = 0 - _last_wait_index = -1 - _last_mutation_index = -1 - - self.is_typing = true - - # Allow typing listeners a chance to connect - await get_tree().process_frame - - if get_total_character_count() == 0: - self.is_typing = false - elif seconds_per_step == 0: - _mutate_remaining_mutations() - visible_characters = get_total_character_count() - self.is_typing = false - - -## Stop typing out the text and jump right to the end -func skip_typing() -> void: - _mutate_remaining_mutations() - visible_characters = get_total_character_count() - self.is_typing = false - skipped_typing.emit() - - -# Type out the next character(s) -func _type_next(delta: float, seconds_needed: float) -> void: - if _is_awaiting_mutation: return - - if visible_characters == get_total_character_count(): - return - - if _last_mutation_index != visible_characters: - _last_mutation_index = visible_characters - _mutate_inline_mutations(visible_characters) - if _is_awaiting_mutation: return - - var additional_waiting_seconds: float = _get_pause(visible_characters) - - # Pause on characters like "." - if _should_auto_pause(): - additional_waiting_seconds += seconds_per_pause_step - - # Pause at literal [wait] directives - if _last_wait_index != visible_characters and additional_waiting_seconds > 0: - _last_wait_index = visible_characters - _waiting_seconds += additional_waiting_seconds - paused_typing.emit(_get_pause(visible_characters)) - else: - visible_characters += 1 - if visible_characters <= get_total_character_count(): - spoke.emit(get_parsed_text()[visible_characters - 1], visible_characters - 1, _get_speed(visible_characters)) - # See if there's time to type out some more in this frame - seconds_needed += seconds_per_step * (1.0 / _get_speed(visible_characters)) - if seconds_needed > delta: - _waiting_seconds += seconds_needed - else: - _type_next(delta, seconds_needed) - - -# Get the pause for the current typing position if there is one -func _get_pause(at_index: int) -> float: - return dialogue_line.pauses.get(at_index, 0) - - -# Get the speed for the current typing position -func _get_speed(at_index: int) -> float: - var speed: float = 1 - for index in dialogue_line.speeds: - if index > at_index: - return speed - speed = dialogue_line.speeds[index] - return speed - - -# Run any inline mutations that haven't been run yet -func _mutate_remaining_mutations() -> void: - for i in range(visible_characters, get_total_character_count() + 1): - _mutate_inline_mutations(i) - - -# Run any mutations at the current typing position -func _mutate_inline_mutations(index: int) -> void: - for inline_mutation in dialogue_line.inline_mutations: - # inline mutations are an array of arrays in the form of [character index, resolvable function] - if inline_mutation[0] > index: - return - if inline_mutation[0] == index: - _is_awaiting_mutation = true - # The DialogueManager can't be referenced directly here so we need to get it by its path - await Engine.get_singleton("DialogueManager").mutate(inline_mutation[1], dialogue_line.extra_game_states, true) - _is_awaiting_mutation = false - - -# Determine if the current autopause character at the cursor should qualify to pause typing. -func _should_auto_pause() -> bool: - if visible_characters == 0: return false - - var parsed_text: String = get_parsed_text() - - # Avoid outofbounds when the label auto-translates and the text changes to one shorter while typing out - # Note: visible characters can be larger than parsed_text after a translation event - if visible_characters >= parsed_text.length(): return false - - # Ignore pause characters if they are next to a non-pause character - if parsed_text[visible_characters] in skip_pause_at_character_if_followed_by.split(): - return false - - # Ignore "." if it's between two numbers - if visible_characters > 3 and parsed_text[visible_characters - 1] == ".": - var possible_number: String = parsed_text.substr(visible_characters - 2, 3) - if str(float(possible_number)) == possible_number: - return false - - # Ignore "." if it's used in an abbreviation - # Note: does NOT support multi-period abbreviations (ex. p.m.) - if "." in pause_at_characters and parsed_text[visible_characters - 1] == ".": - for abbreviation in skip_pause_at_abbreviations: - if visible_characters >= abbreviation.length(): - var previous_characters: String = parsed_text.substr(visible_characters - abbreviation.length() - 1, abbreviation.length()) - if previous_characters == abbreviation: - return false - - # Ignore two non-"." characters next to each other - var other_pause_characters: PackedStringArray = pause_at_characters.replace(".", "").split() - if visible_characters > 1 and parsed_text[visible_characters - 1] in other_pause_characters and parsed_text[visible_characters] in other_pause_characters: - return false - - return parsed_text[visible_characters - 1] in pause_at_characters.split() diff --git a/addons/dialogue_manager/dialogue_label.tscn b/addons/dialogue_manager/dialogue_label.tscn deleted file mode 100644 index df48b64..0000000 --- a/addons/dialogue_manager/dialogue_label.tscn +++ /dev/null @@ -1,19 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://ckvgyvclnwggo"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_label.gd" id="1_cital"] - -[node name="DialogueLabel" type="RichTextLabel"] -anchors_preset = 10 -anchor_right = 1.0 -grow_horizontal = 2 -mouse_filter = 1 -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 = 1 -script = ExtResource("1_cital") -skip_pause_at_abbreviations = PackedStringArray("Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex") diff --git a/addons/dialogue_manager/dialogue_line.gd b/addons/dialogue_manager/dialogue_line.gd deleted file mode 100644 index a9bf84a..0000000 --- a/addons/dialogue_manager/dialogue_line.gd +++ /dev/null @@ -1,98 +0,0 @@ -## A line of dialogue returned from [code]DialogueManager[/code]. -class_name DialogueLine extends RefCounted - - -const _DialogueConstants = preload("./constants.gd") - - -## The ID of this line -var id: String - -## The internal type of this dialogue object. One of [code]TYPE_DIALOGUE[/code] or [code]TYPE_MUTATION[/code] -var type: String = _DialogueConstants.TYPE_DIALOGUE - -## The next line ID after this line. -var next_id: String = "" - -## The character name that is saying this line. -var character: String = "" - -## A dictionary of variable replacements fo the character name. Generally for internal use only. -var character_replacements: Array[Dictionary] = [] - -## The dialogue being spoken. -var text: String = "" - -## A dictionary of replacements for the text. Generally for internal use only. -var text_replacements: Array[Dictionary] = [] - -## The key to use for translating this line. -var translation_key: String = "" - -## A map for when and for how long to pause while typing out the dialogue text. -var pauses: Dictionary = {} - -## A map for speed changes when typing out the dialogue text. -var speeds: Dictionary = {} - -## A map of any mutations to run while typing out the dialogue text. -var inline_mutations: Array[Array] = [] - -## A list of responses attached to this line of dialogue. -var responses: Array[DialogueResponse] = [] - -## A list of any extra game states to check when resolving variables and mutations. -var extra_game_states: Array = [] - -## How long to show this line before advancing to the next. Either a float (of seconds), [code]"auto"[/code], or [code]null[/code]. -var time: String = "" - -## Any #tags that were included in the line -var tags: PackedStringArray = [] - -## The mutation details if this is a mutation line (where [code]type == TYPE_MUTATION[/code]). -var mutation: Dictionary = {} - -## The conditions to check before including this line in the flow of dialogue. If failed the line will be skipped over. -var conditions: Dictionary = {} - - -func _init(data: Dictionary = {}) -> void: - if data.size() > 0: - id = data.id - next_id = data.next_id - type = data.type - extra_game_states = data.get("extra_game_states", []) - - match type: - _DialogueConstants.TYPE_DIALOGUE: - character = data.character - character_replacements = data.get("character_replacements", [] as Array[Dictionary]) - text = data.text - text_replacements = data.get("text_replacements", [] as Array[Dictionary]) - translation_key = data.get("translation_key", data.text) - pauses = data.get("pauses", {}) - speeds = data.get("speeds", {}) - inline_mutations = data.get("inline_mutations", [] as Array[Array]) - time = data.get("time", "") - tags = data.get("tags", []) - - _DialogueConstants.TYPE_MUTATION: - mutation = data.mutation - - -func _to_string() -> String: - match type: - _DialogueConstants.TYPE_DIALOGUE: - return "<DialogueLine character=\"%s\" text=\"%s\">" % [character, text] - _DialogueConstants.TYPE_MUTATION: - return "<DialogueLine mutation>" - return "" - - -func get_tag_value(tag_name: String) -> String: - var wrapped := "%s=" % tag_name - for t in tags: - if t.begins_with(wrapped): - return t.replace(wrapped, "").strip_edges() - return "" diff --git a/addons/dialogue_manager/dialogue_manager.gd b/addons/dialogue_manager/dialogue_manager.gd deleted file mode 100644 index 57d7f86..0000000 --- a/addons/dialogue_manager/dialogue_manager.gd +++ /dev/null @@ -1,1235 +0,0 @@ -extends Node - - -const DialogueConstants = preload("./constants.gd") -const Builtins = preload("./utilities/builtins.gd") -const DialogueSettings = preload("./settings.gd") -const DialogueResource = preload("./dialogue_resource.gd") -const DialogueLine = preload("./dialogue_line.gd") -const DialogueResponse = preload("./dialogue_response.gd") -const DialogueManagerParser = preload("./components/parser.gd") -const DialogueManagerParseResult = preload("./components/parse_result.gd") -const ResolvedLineData = preload("./components/resolved_line_data.gd") - - -## Emitted when a title is encountered while traversing dialogue, usually when jumping from a -## goto line -signal passed_title(title: String) - -## Emitted when a line of dialogue is encountered. -signal got_dialogue(line: DialogueLine) - -## Emitted when a mutation is encountered. -signal mutated(mutation: Dictionary) - -## Emitted when some dialogue has reached the end. -signal dialogue_ended(resource: DialogueResource) - -## Used internally. -signal bridge_get_next_dialogue_line_completed(line: DialogueLine) - -## Used inernally -signal bridge_mutated() - - -enum MutationBehaviour { - Wait, - DoNotWait, - Skip -} - -enum TranslationSource { - None, - Guess, - CSV, - PO -} - - -## The list of globals that dialogue can query -var game_states: Array = [] - -## Allow dialogue to call singletons -var include_singletons: bool = true - -## Allow dialogue to call static methods/properties on classes -var include_classes: bool = true - -## Manage translation behaviour -var translation_source: TranslationSource = TranslationSource.Guess - -## Used to resolve the current scene. Override if your game manages the current scene itself. -var get_current_scene: Callable = func(): - var current_scene: Node = get_tree().current_scene - if current_scene == null: - current_scene = get_tree().root.get_child(get_tree().root.get_child_count() - 1) - return current_scene - -var _has_loaded_autoloads: bool = false -var _autoloads: Dictionary = {} - - -var _node_properties: Array = [] - - -func _ready() -> void: - # Cache the known Node2D properties - _node_properties = ["Script Variables"] - var temp_node: Node2D = Node2D.new() - for property in temp_node.get_property_list(): - _node_properties.append(property.name) - temp_node.free() - - # Make the dialogue manager available as a singleton - if Engine.has_singleton("DialogueManager"): - Engine.unregister_singleton("DialogueManager") - Engine.register_singleton("DialogueManager", self) - - # Connect up the C# signals if need be - if DialogueSettings.has_dotnet_solution(): - _get_dotnet_dialogue_manager().Prepare() - - -## Step through lines and run any mutations until we either hit some dialogue or the end of the conversation -func get_next_dialogue_line(resource: DialogueResource, key: String = "", extra_game_states: Array = [], mutation_behaviour: MutationBehaviour = MutationBehaviour.Wait) -> DialogueLine: - # You have to provide a valid dialogue resource - if resource == null: - assert(false, DialogueConstants.translate(&"runtime.no_resource")) - if resource.lines.size() == 0: - assert(false, DialogueConstants.translate(&"runtime.no_content").format({ file_path = resource.resource_path })) - - # Inject any "using" states into the game_states - for state_name in resource.using_states: - var autoload = get_tree().root.get_node_or_null(state_name) - if autoload == null: - printerr(DialogueConstants.translate(&"runtime.unknown_autoload").format({ autoload = state_name })) - else: - extra_game_states = [autoload] + extra_game_states - - # Get the line data - var dialogue: DialogueLine = await get_line(resource, key, extra_game_states) - - # If our dialogue is nothing then we hit the end - if not is_valid(dialogue): - (func(): dialogue_ended.emit(resource)).call_deferred() - return null - - # Run the mutation if it is one - if dialogue.type == DialogueConstants.TYPE_MUTATION: - var actual_next_id: String = dialogue.next_id.split(",")[0] - match mutation_behaviour: - MutationBehaviour.Wait: - await mutate(dialogue.mutation, extra_game_states) - MutationBehaviour.DoNotWait: - mutate(dialogue.mutation, extra_game_states) - MutationBehaviour.Skip: - pass - if actual_next_id in [DialogueConstants.ID_END_CONVERSATION, DialogueConstants.ID_NULL, null]: - # End the conversation - (func(): dialogue_ended.emit(resource)).call_deferred() - return null - else: - return await get_next_dialogue_line(resource, dialogue.next_id, extra_game_states, mutation_behaviour) - else: - got_dialogue.emit(dialogue) - return dialogue - - -func get_resolved_line_data(data: Dictionary, extra_game_states: Array = []) -> ResolvedLineData: - var text: String = translate(data) - - # Resolve variables - for replacement in data.text_replacements: - var value = await resolve(replacement.expression.duplicate(true), extra_game_states) - var index: int = text.find(replacement.value_in_text) - text = text.substr(0, index) + str(value) + text.substr(index + replacement.value_in_text.length()) - - var parser: DialogueManagerParser = DialogueManagerParser.new() - - # Resolve random groups - for found in parser.INLINE_RANDOM_REGEX.search_all(text): - var options = found.get_string(&"options").split(&"|") - text = text.replace(&"[[%s]]" % found.get_string(&"options"), options[randi_range(0, options.size() - 1)]) - - # Do a pass on the markers to find any conditionals - var markers: ResolvedLineData = parser.extract_markers(text) - - # Resolve any conditionals and update marker positions as needed - if data.type == DialogueConstants.TYPE_DIALOGUE: - var resolved_text: String = markers.text - var conditionals: Array[RegExMatch] = parser.INLINE_CONDITIONALS_REGEX.search_all(resolved_text) - var replacements: Array = [] - for conditional in conditionals: - var condition_raw: String = conditional.strings[conditional.names.condition] - var body: String = conditional.strings[conditional.names.body] - var body_else: String = "" - if &"[else]" in body: - var bits = body.split(&"[else]") - body = bits[0] - body_else = bits[1] - var condition: Dictionary = parser.extract_condition("if " + condition_raw, false, 0) - # If the condition fails then use the else of "" - if not await check_condition({ condition = condition }, extra_game_states): - body = body_else - replacements.append({ - start = conditional.get_start(), - end = conditional.get_end(), - string = conditional.get_string(), - body = body - }) - - for i in range(replacements.size() -1, -1, -1): - var r: Dictionary = replacements[i] - resolved_text = resolved_text.substr(0, r.start) + r.body + resolved_text.substr(r.end, 9999) - # Move any other markers now that the text has changed - var offset: int = r.end - r.start - r.body.length() - for key in [&"pauses", &"speeds", &"time"]: - if markers.get(key) == null: continue - var marker = markers.get(key) - var next_marker: Dictionary = {} - for index in marker: - if index < r.start: - next_marker[index] = marker[index] - elif index > r.start: - next_marker[index - offset] = marker[index] - markers.set(key, next_marker) - var mutations: Array[Array] = markers.mutations - var next_mutations: Array[Array] = [] - for mutation in mutations: - var index = mutation[0] - if index < r.start: - next_mutations.append(mutation) - elif index > r.start: - next_mutations.append([index - offset, mutation[1]]) - markers.mutations = next_mutations - - markers.text = resolved_text - - parser.free() - - return markers - - -## Replace any variables, etc in the character name -func get_resolved_character(data: Dictionary, extra_game_states: Array = []) -> String: - var character: String = data.get(&"character", "") - - # Resolve variables - for replacement in data.get(&"character_replacements", []): - var value = await resolve(replacement.expression.duplicate(true), extra_game_states) - var index: int = character.find(replacement.value_in_text) - character = character.substr(0, index) + str(value) + character.substr(index + replacement.value_in_text.length()) - - # Resolve random groups - var random_regex: RegEx = RegEx.new() - random_regex.compile("\\[\\[(?<options>.*?)\\]\\]") - for found in random_regex.search_all(character): - var options = found.get_string(&"options").split("|") - character = character.replace("[[%s]]" % found.get_string(&"options"), options[randi_range(0, options.size() - 1)]) - - return character - - -## Generate a dialogue resource on the fly from some text -func create_resource_from_text(text: String) -> Resource: - var parser: DialogueManagerParser = DialogueManagerParser.new() - parser.parse(text, "") - var results: DialogueManagerParseResult = parser.get_data() - var errors: Array[Dictionary] = parser.get_errors() - parser.free() - - if errors.size() > 0: - printerr(DialogueConstants.translate(&"runtime.errors").format({ count = errors.size() })) - for error in errors: - printerr(DialogueConstants.translate(&"runtime.error_detail").format({ - line = error.line_number + 1, - message = DialogueConstants.get_error_message(error.error) - })) - assert(false, DialogueConstants.translate(&"runtime.errors_see_details").format({ count = errors.size() })) - - var resource: DialogueResource = DialogueResource.new() - resource.using_states = results.using_states - resource.titles = results.titles - resource.first_title = results.first_title - resource.character_names = results.character_names - resource.lines = results.lines - resource.raw_text = text - - return resource - - -## Show the example balloon -func show_example_dialogue_balloon(resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> CanvasLayer: - var balloon: Node = load(_get_example_balloon_path()).instantiate() - get_current_scene.call().add_child(balloon) - balloon.start(resource, title, extra_game_states) - - return balloon - - -## Show the configured dialogue balloon -func show_dialogue_balloon(resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> Node: - var balloon_path: String = DialogueSettings.get_setting(&"balloon_path", _get_example_balloon_path()) - if not ResourceLoader.exists(balloon_path): - balloon_path = _get_example_balloon_path() - return show_dialogue_balloon_scene(balloon_path, resource, title, extra_game_states) - - -## Show a given balloon scene -func show_dialogue_balloon_scene(balloon_scene, resource: DialogueResource, title: String = "", extra_game_states: Array = []) -> Node: - if balloon_scene is String: - balloon_scene = load(balloon_scene) - if balloon_scene is PackedScene: - balloon_scene = balloon_scene.instantiate() - - var balloon: Node = balloon_scene - get_current_scene.call().add_child(balloon) - if balloon.has_method(&"start"): - balloon.start(resource, title, extra_game_states) - elif balloon.has_method(&"Start"): - balloon.Start(resource, title, extra_game_states) - else: - assert(false, DialogueConstants.translate(&"runtime.dialogue_balloon_missing_start_method")) - return balloon - - -# Get the path to the example balloon -func _get_example_balloon_path() -> String: - var is_small_window: bool = ProjectSettings.get_setting("display/window/size/viewport_width") < 400 - var balloon_path: String = "/example_balloon/small_example_balloon.tscn" if is_small_window else "/example_balloon/example_balloon.tscn" - return get_script().resource_path.get_base_dir() + balloon_path - - -### Dotnet bridge - - -func _get_dotnet_dialogue_manager() -> Node: - return load(get_script().resource_path.get_base_dir() + "/DialogueManager.cs").new() - - -func _bridge_get_next_dialogue_line(resource: DialogueResource, key: String, extra_game_states: Array = []) -> void: - # dotnet needs at least one await tick of the signal gets called too quickly - await get_tree().process_frame - - var line = await get_next_dialogue_line(resource, key, extra_game_states) - bridge_get_next_dialogue_line_completed.emit(line) - - -func _bridge_mutate(mutation: Dictionary, extra_game_states: Array, is_inline_mutation: bool = false) -> void: - await mutate(mutation, extra_game_states, is_inline_mutation) - bridge_mutated.emit() - - -### Helpers - - -# Get a line by its ID -func get_line(resource: DialogueResource, key: String, extra_game_states: Array) -> DialogueLine: - key = key.strip_edges() - - # See if we were given a stack instead of just the one key - var stack: Array = key.split("|") - key = stack.pop_front() - var id_trail: String = "" if stack.size() == 0 else "|" + "|".join(stack) - - # Key is blank so just use the first title - if key == null or key == "": - key = resource.first_title - - # See if we just ended the conversation - if key in [DialogueConstants.ID_END, DialogueConstants.ID_NULL, null]: - if stack.size() > 0: - return await get_line(resource, "|".join(stack), extra_game_states) - else: - return null - elif key == DialogueConstants.ID_END_CONVERSATION: - return null - - # See if it is a title - if key.begins_with("~ "): - key = key.substr(2) - if resource.titles.has(key): - key = resource.titles.get(key) - - if key in resource.titles.values(): - passed_title.emit(resource.titles.find_key(key)) - - if not resource.lines.has(key): - assert(false, DialogueConstants.translate(&"errors.key_not_found").format({ key = key })) - - var data: Dictionary = resource.lines.get(key) - - # Check for weighted random lines - if data.has(&"siblings"): - var target_weight: float = randf_range(0, data.siblings.reduce(func(total, sibling): return total + sibling.weight, 0)) - var cummulative_weight: float = 0 - for sibling in data.siblings: - if target_weight < cummulative_weight + sibling.weight: - data = resource.lines.get(sibling.id) - break - else: - cummulative_weight += sibling.weight - - # Check condtiions - if data.type == DialogueConstants.TYPE_CONDITION: - # "else" will have no actual condition - if await check_condition(data, extra_game_states): - return await get_line(resource, data.next_id + id_trail, extra_game_states) - else: - return await get_line(resource, data.next_conditional_id + id_trail, extra_game_states) - - # Evaluate jumps - elif data.type == DialogueConstants.TYPE_GOTO: - if data.is_snippet: - id_trail = "|" + data.next_id_after + id_trail - return await get_line(resource, data.next_id + id_trail, extra_game_states) - - elif data.type == DialogueConstants.TYPE_DIALOGUE: - if not data.has(&"id"): - data.id = key - - # Set up a line object - var line: DialogueLine = await create_dialogue_line(data, extra_game_states) - - # If the jump point somehow has no content then just end - if not line: return null - - # If we are the first of a list of responses then get the other ones - if data.type == DialogueConstants.TYPE_RESPONSE: - # Note: For some reason C# has occasional issues with using the responses property directly - # so instead we use set and get here. - line.set(&"responses", await get_responses(data.get(&"responses", []), resource, id_trail, extra_game_states)) - return line - - # Inject the next node's responses if they have any - if resource.lines.has(line.next_id): - var next_line: Dictionary = resource.lines.get(line.next_id) - - # If the response line is marked as a title then make sure to emit the passed_title signal. - if line.next_id in resource.titles.values(): - passed_title.emit(resource.titles.find_key(line.next_id)) - - # If the next line is a title then check where it points to see if that is a set of responses. - if next_line.type == DialogueConstants.TYPE_GOTO and resource.lines.has(next_line.next_id): - next_line = resource.lines.get(next_line.next_id) - - if next_line != null and next_line.type == DialogueConstants.TYPE_RESPONSE: - # Note: For some reason C# has occasional issues with using the responses property directly - # so instead we use set and get here. - line.set(&"responses", await get_responses(next_line.get(&"responses", []), resource, id_trail, extra_game_states)) - - line.next_id = "|".join(stack) if line.next_id == DialogueConstants.ID_NULL else line.next_id + id_trail - return line - - -# Show a message or crash with error -func show_error_for_missing_state_value(message: String, will_show: bool = true) -> void: - if not will_show: return - - if DialogueSettings.get_setting(&"ignore_missing_state_values", false): - push_error(message) - elif will_show: - # If you're here then you're missing a method or property in your game state. The error - # message down in the debugger will give you some more information. - assert(false, message) - - -# Translate a string -func translate(data: Dictionary) -> String: - if translation_source == TranslationSource.None: - return data.text - - if data.translation_key == "" or data.translation_key == data.text: - return tr(data.text) - else: - # Line IDs work slightly differently depending on whether the translation came from a - # CSV or a PO file. CSVs use the line ID (or the line itself) as the translatable string - # whereas POs use the ID as context and the line itself as the translatable string. - match translation_source: - TranslationSource.PO: - return tr(data.text, StringName(data.translation_key)) - - TranslationSource.CSV: - return tr(data.translation_key) - - TranslationSource.Guess: - var translation_files: Array = ProjectSettings.get_setting(&"internationalization/locale/translations") - if translation_files.filter(func(f: String): return f.get_extension() == &"po").size() > 0: - # Assume PO - return tr(data.text, StringName(data.translation_key)) - else: - # Assume CSV - return tr(data.translation_key) - - return tr(data.translation_key) - - -# Create a line of dialogue -func create_dialogue_line(data: Dictionary, extra_game_states: Array) -> DialogueLine: - match data.type: - DialogueConstants.TYPE_DIALOGUE: - var resolved_data: ResolvedLineData = await get_resolved_line_data(data, extra_game_states) - return DialogueLine.new({ - id = data.get(&"id", ""), - type = DialogueConstants.TYPE_DIALOGUE, - next_id = data.next_id, - character = await get_resolved_character(data, extra_game_states), - character_replacements = data.character_replacements, - text = resolved_data.text, - text_replacements = data.text_replacements, - translation_key = data.translation_key, - pauses = resolved_data.pauses, - speeds = resolved_data.speeds, - inline_mutations = resolved_data.mutations, - time = resolved_data.time, - tags = data.get(&"tags", []), - extra_game_states = extra_game_states - }) - - DialogueConstants.TYPE_RESPONSE: - return DialogueLine.new({ - id = data.get(&"id", ""), - type = DialogueConstants.TYPE_RESPONSE, - next_id = data.next_id, - tags = data.get(&"tags", []), - extra_game_states = extra_game_states - }) - - DialogueConstants.TYPE_MUTATION: - return DialogueLine.new({ - id = data.get(&"id", ""), - type = DialogueConstants.TYPE_MUTATION, - next_id = data.next_id, - mutation = data.mutation, - extra_game_states = extra_game_states - }) - - return null - - -# Create a response -func create_response(data: Dictionary, extra_game_states: Array) -> DialogueResponse: - var resolved_data: ResolvedLineData = await get_resolved_line_data(data, extra_game_states) - return DialogueResponse.new({ - id = data.get(&"id", ""), - type = DialogueConstants.TYPE_RESPONSE, - next_id = data.next_id, - is_allowed = data.is_allowed, - character = await get_resolved_character(data, extra_game_states), - character_replacements = data.get(&"character_replacements", [] as Array[Dictionary]), - text = resolved_data.text, - text_replacements = data.text_replacements, - tags = data.get(&"tags", []), - translation_key = data.translation_key - }) - - -# Get the current game states -func get_game_states(extra_game_states: Array) -> Array: - if not _has_loaded_autoloads: - _has_loaded_autoloads = true - # Add any autoloads to a generic state so we can refer to them by name - for child in get_tree().root.get_children(): - # Ignore the dialogue manager - if child.name == &"DialogueManager": continue - # Ignore the current main scene - if get_tree().current_scene and child.name == get_tree().current_scene.name: continue - # Add the node to our known autoloads - _autoloads[child.name] = child - game_states = [_autoloads] - # Add any other state shortcuts from settings - for node_name in DialogueSettings.get_setting(&"states", []): - var state: Node = get_node_or_null("/root/" + node_name) - if state: - game_states.append(state) - - var current_scene: Node = get_current_scene.call() - var unique_states: Array = [] - for state in extra_game_states + [current_scene] + game_states: - if state != null and not unique_states.has(state): - unique_states.append(state) - return unique_states - - -# Check if a condition is met -func check_condition(data: Dictionary, extra_game_states: Array) -> bool: - if data.get(&"condition", null) == null: return true - if data.condition.size() == 0: return true - - return await resolve(data.condition.expression.duplicate(true), extra_game_states) - - -# Make a change to game state or run a method -func mutate(mutation: Dictionary, extra_game_states: Array, is_inline_mutation: bool = false) -> void: - var expression: Array[Dictionary] = mutation.expression - - # Handle built in mutations - if expression[0].type == DialogueConstants.TOKEN_FUNCTION and expression[0].function in [&"wait", &"debug"]: - var args: Array = await resolve_each(expression[0].value, extra_game_states) - match expression[0].function: - &"wait": - mutated.emit(mutation) - await get_tree().create_timer(float(args[0])).timeout - return - - &"debug": - prints("Debug:", args) - await get_tree().process_frame - - # Or pass through to the resolver - else: - if not mutation_contains_assignment(mutation.expression) and not is_inline_mutation: - mutated.emit(mutation) - - if mutation.get("is_blocking", true): - await resolve(mutation.expression.duplicate(true), extra_game_states) - return - else: - resolve(mutation.expression.duplicate(true), extra_game_states) - - # Wait one frame to give the dialogue handler a chance to yield - await get_tree().process_frame - - -func mutation_contains_assignment(mutation: Array) -> bool: - for token in mutation: - if token.type == DialogueConstants.TOKEN_ASSIGNMENT: - return true - return false - - -func resolve_each(array: Array, extra_game_states: Array) -> Array: - var results: Array = [] - for item in array: - results.append(await resolve(item.duplicate(true), extra_game_states)) - return results - - -# Replace an array of line IDs with their response prompts -func get_responses(ids: Array, resource: DialogueResource, id_trail: String, extra_game_states: Array) -> Array[DialogueResponse]: - var responses: Array[DialogueResponse] = [] - for id in ids: - var data: Dictionary = resource.lines.get(id).duplicate(true) - data.is_allowed = await check_condition(data, extra_game_states) - if DialogueSettings.get_setting(&"include_all_responses", false) or data.is_allowed: - var response: DialogueResponse = await create_response(data, extra_game_states) - response.next_id += id_trail - responses.append(response) - - return responses - - -# Get a value on the current scene or game state -func get_state_value(property: String, extra_game_states: Array): - # Special case for static primitive calls - if property == "Color": - return Color() - elif property == "Vector2": - return Vector2.ZERO - elif property == "Vector3": - return Vector3.ZERO - elif property == "Vector4": - return Vector4.ZERO - elif property == "Quaternian": - return Quaternion() - - var expression = Expression.new() - if expression.parse(property) != OK: - assert(false, DialogueConstants.translate(&"runtime.invalid_expression").format({ expression = property, error = expression.get_error_text() })) - - for state in get_game_states(extra_game_states): - if typeof(state) == TYPE_DICTIONARY: - if state.has(property): - return state.get(property) - else: - var result = expression.execute([], state, false) - if not expression.has_execute_failed(): - return result - - if include_singletons and Engine.has_singleton(property): - return Engine.get_singleton(property) - - if include_classes: - for class_data in ProjectSettings.get_global_class_list(): - if class_data.get(&"class") == property: - return load(class_data.path).new() - - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found").format({ property = property, states = str(get_game_states(extra_game_states)) })) - - -# Set a value on the current scene or game state -func set_state_value(property: String, value, extra_game_states: Array) -> void: - for state in get_game_states(extra_game_states): - if typeof(state) == TYPE_DICTIONARY: - if state.has(property): - state[property] = value - return - elif thing_has_property(state, property): - state.set(property, value) - return - - if property.to_snake_case() != property: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found_missing_export").format({ property = property, states = str(get_game_states(extra_game_states)) })) - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.property_not_found").format({ property = property, states = str(get_game_states(extra_game_states)) })) - - -# Collapse any expressions -func resolve(tokens: Array, extra_game_states: Array): - # Handle groups first - for token in tokens: - if token.type == DialogueConstants.TOKEN_GROUP: - token["type"] = "value" - token["value"] = await resolve(token.value, extra_game_states) - - # Then variables/methods - var i: int = 0 - var limit: int = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - - if token.type == DialogueConstants.TOKEN_FUNCTION: - var function_name: String = token.function - var args = await resolve_each(token.value, extra_game_states) - if tokens[i - 1].type == DialogueConstants.TOKEN_DOT: - # If we are calling a deeper function then we need to collapse the - # value into the thing we are calling the function on - var caller: Dictionary = tokens[i - 2] - if Builtins.is_supported(caller.value): - caller["type"] = "value" - caller["value"] = Builtins.resolve_method(caller.value, function_name, args) - tokens.remove_at(i) - tokens.remove_at(i-1) - i -= 2 - elif thing_has_method(caller.value, function_name, args): - caller["type"] = "value" - caller["value"] = await resolve_thing_method(caller.value, function_name, args) - tokens.remove_at(i) - tokens.remove_at(i-1) - i -= 2 - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.method_not_callable").format({ method = function_name, object = str(caller.value) })) - else: - var found: bool = false - match function_name: - &"str": - token["type"] = "value" - token["value"] = str(args[0]) - found = true - &"Vector2": - token["type"] = "value" - token["value"] = Vector2(args[0], args[1]) - found = true - &"Vector2i": - token["type"] = "value" - token["value"] = Vector2i(args[0], args[1]) - found = true - &"Vector3": - token["type"] = "value" - token["value"] = Vector3(args[0], args[1], args[2]) - found = true - &"Vector3i": - token["type"] = "value" - token["value"] = Vector3i(args[0], args[1], args[2]) - found = true - &"Vector4": - token["type"] = "value" - token["value"] = Vector4(args[0], args[1], args[2], args[3]) - found = true - &"Vector4i": - token["type"] = "value" - token["value"] = Vector4i(args[0], args[1], args[2], args[3]) - found = true - &"Quaternion": - token["type"] = "value" - token["value"] = Quaternion(args[0], args[1], args[2], args[3]) - found = true - &"Color": - token["type"] = "value" - match args.size(): - 0: - token["value"] = Color() - 1: - token["value"] = Color(args[0]) - 2: - token["value"] = Color(args[0], args[1]) - 3: - token["value"] = Color(args[0], args[1], args[2]) - 4: - token["value"] = Color(args[0], args[1], args[2], args[3]) - found = true - &"load": - token["type"] = "value" - token["value"] = load(args[0]) - found = true - &"emit": - token["type"] = "value" - token["value"] = resolve_signal(args, extra_game_states) - found = true - _: - for state in get_game_states(extra_game_states): - if thing_has_method(state, function_name, args): - token["type"] = "value" - token["value"] = await resolve_thing_method(state, function_name, args) - found = true - break - - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.method_not_found").format({ - method = args[0] if function_name in ["call", "call_deferred"] else function_name, - states = str(get_game_states(extra_game_states)) - }), not found) - - elif token.type == DialogueConstants.TOKEN_DICTIONARY_REFERENCE: - var value - if i > 0 and tokens[i - 1].type == DialogueConstants.TOKEN_DOT: - # If we are deep referencing then we need to get the parent object. - # `parent.value` is the actual object and `token.variable` is the name of - # the property within it. - value = tokens[i - 2].value[token.variable] - # Clean up the previous tokens - token.erase("variable") - tokens.remove_at(i - 1) - tokens.remove_at(i - 2) - i -= 2 - else: - # Otherwise we can just get this variable as a normal state reference - value = get_state_value(token.variable, extra_game_states) - - var index = await resolve(token.value, extra_game_states) - if typeof(value) == TYPE_DICTIONARY: - if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # If the next token is an assignment then we need to leave this as a reference - # so that it can be resolved once everything ahead of it has been resolved - token["type"] = "dictionary" - token["value"] = value - token["key"] = index - else: - if value.has(index): - token["type"] = "value" - token["value"] = value[index] - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.key_not_found").format({ key = str(index), dictionary = token.variable })) - elif typeof(value) == TYPE_ARRAY: - if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # If the next token is an assignment then we need to leave this as a reference - # so that it can be resolved once everything ahead of it has been resolved - token["type"] = "array" - token["value"] = value - token["key"] = index - else: - if index >= 0 and index < value.size(): - token["type"] = "value" - token["value"] = value[index] - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = index, array = token.variable })) - - elif token.type == DialogueConstants.TOKEN_DICTIONARY_NESTED_REFERENCE: - var dictionary: Dictionary = tokens[i - 1] - var index = await resolve(token.value, extra_game_states) - var value = dictionary.value - if typeof(value) == TYPE_DICTIONARY: - if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # If the next token is an assignment then we need to leave this as a reference - # so that it can be resolved once everything ahead of it has been resolved - dictionary["type"] = "dictionary" - dictionary["key"] = index - dictionary["value"] = value - tokens.remove_at(i) - i -= 1 - else: - if dictionary.value.has(index): - dictionary["value"] = value.get(index) - tokens.remove_at(i) - i -= 1 - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.key_not_found").format({ key = str(index), dictionary = value })) - elif typeof(value) == TYPE_ARRAY: - if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # If the next token is an assignment then we need to leave this as a reference - # so that it can be resolved once everything ahead of it has been resolved - dictionary["type"] = "array" - dictionary["value"] = value - dictionary["key"] = index - tokens.remove_at(i) - i -= 1 - else: - if index >= 0 and index < value.size(): - dictionary["value"] = value[index] - tokens.remove_at(i) - i -= 1 - else: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = index, array = value })) - - elif token.type == DialogueConstants.TOKEN_ARRAY: - token["type"] = "value" - token["value"] = await resolve_each(token.value, extra_game_states) - - elif token.type == DialogueConstants.TOKEN_DICTIONARY: - token["type"] = "value" - var dictionary = {} - for key in token.value.keys(): - var resolved_key = await resolve([key], extra_game_states) - var preresolved_value = token.value.get(key) - if typeof(preresolved_value) != TYPE_ARRAY: - preresolved_value = [preresolved_value] - var resolved_value = await resolve(preresolved_value, extra_game_states) - dictionary[resolved_key] = resolved_value - token["value"] = dictionary - - elif token.type == DialogueConstants.TOKEN_VARIABLE or token.type == DialogueConstants.TOKEN_NUMBER: - if str(token.value) == "null": - token["type"] = "value" - token["value"] = null - elif tokens[i - 1].type == DialogueConstants.TOKEN_DOT: - var caller: Dictionary = tokens[i - 2] - var property = token.value - if tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # If the next token is an assignment then we need to leave this as a reference - # so that it can be resolved once everything ahead of it has been resolved - caller["type"] = "property" - caller["property"] = property - else: - # If we are requesting a deeper property then we need to collapse the - # value into the thing we are referencing from - caller["type"] = "value" - if Builtins.is_supported(caller.value): - caller["value"] = Builtins.resolve_property(caller.value, property) - else: - caller["value"] = caller.value.get(property) - tokens.remove_at(i) - tokens.remove_at(i-1) - i -= 2 - elif tokens.size() > i + 1 and tokens[i + 1].type == DialogueConstants.TOKEN_ASSIGNMENT: - # It's a normal variable but we will be assigning to it so don't resolve - # it until everything after it has been resolved - token["type"] = "variable" - else: - token["type"] = "value" - token["value"] = get_state_value(str(token.value), extra_game_states) - - i += 1 - - # Then multiply and divide - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_OPERATOR and token.value in ["*", "/", "%"]: - token["type"] = "value" - token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) - tokens.remove_at(i+1) - tokens.remove_at(i-1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - # Then addition and subtraction - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_OPERATOR and token.value in ["+", "-"]: - token["type"] = "value" - token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) - tokens.remove_at(i+1) - tokens.remove_at(i-1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - # Then negations - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_NOT: - token["type"] = "value" - token["value"] = not tokens[i+1].value - tokens.remove_at(i+1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - # Then comparisons - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_COMPARISON: - token["type"] = "value" - token["value"] = compare(token.value, tokens[i-1].value, tokens[i+1].value) - tokens.remove_at(i+1) - tokens.remove_at(i-1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - # Then and/or - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_AND_OR: - token["type"] = "value" - token["value"] = apply_operation(token.value, tokens[i-1].value, tokens[i+1].value) - tokens.remove_at(i+1) - tokens.remove_at(i-1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - # Lastly, resolve any assignments - i = 0 - limit = 0 - while i < tokens.size() and limit < 1000: - limit += 1 - var token: Dictionary = tokens[i] - if token.type == DialogueConstants.TOKEN_ASSIGNMENT: - var lhs: Dictionary = tokens[i - 1] - var value - - match lhs.type: - &"variable": - value = apply_operation(token.value, get_state_value(lhs.value, extra_game_states), tokens[i+1].value) - set_state_value(lhs.value, value, extra_game_states) - &"property": - value = apply_operation(token.value, lhs.value.get(lhs.property), tokens[i+1].value) - if typeof(lhs.value) == TYPE_DICTIONARY: - lhs.value[lhs.property] = value - else: - lhs.value.set(lhs.property, value) - &"dictionary": - value = apply_operation(token.value, lhs.value.get(lhs.key, null), tokens[i+1].value) - lhs.value[lhs.key] = value - &"array": - show_error_for_missing_state_value( - DialogueConstants.translate(&"runtime.array_index_out_of_bounds").format({ index = lhs.key, array = lhs.value }), - lhs.key >= lhs.value.size() - ) - value = apply_operation(token.value, lhs.value[lhs.key], tokens[i+1].value) - lhs.value[lhs.key] = value - _: - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.left_hand_size_cannot_be_assigned_to")) - - token["type"] = "value" - token["value"] = value - tokens.remove_at(i+1) - tokens.remove_at(i-1) - i -= 1 - i += 1 - - if limit >= 1000: - assert(false, DialogueConstants.translate(&"runtime.something_went_wrong")) - - return tokens[0].value - - -func compare(operator: String, first_value, second_value) -> bool: - match operator: - &"in": - if first_value == null or second_value == null: - return false - else: - return first_value in second_value - &"<": - if first_value == null: - return true - elif second_value == null: - return false - else: - return first_value < second_value - &">": - if first_value == null: - return false - elif second_value == null: - return true - else: - return first_value > second_value - &"<=": - if first_value == null: - return true - elif second_value == null: - return false - else: - return first_value <= second_value - &">=": - if first_value == null: - return false - elif second_value == null: - return true - else: - return first_value >= second_value - &"==": - if first_value == null: - if typeof(second_value) == TYPE_BOOL: - return second_value == false - else: - return second_value == null - else: - return first_value == second_value - &"!=": - if first_value == null: - if typeof(second_value) == TYPE_BOOL: - return second_value == true - else: - return second_value != null - else: - return first_value != second_value - - return false - - -func apply_operation(operator: String, first_value, second_value): - match operator: - &"=": - return second_value - &"+", &"+=": - return first_value + second_value - &"-", &"-=": - return first_value - second_value - &"/", &"/=": - return first_value / second_value - &"*", &"*=": - return first_value * second_value - &"%": - return first_value % second_value - &"and": - return first_value and second_value - &"or": - return first_value or second_value - - assert(false, DialogueConstants.translate(&"runtime.unknown_operator")) - - -# Check if a dialogue line contains meaningful information -func is_valid(line: DialogueLine) -> bool: - if line == null: - return false - if line.type == DialogueConstants.TYPE_MUTATION and line.mutation == null: - return false - if line.type == DialogueConstants.TYPE_RESPONSE and line.get(&"responses").size() == 0: - return false - return true - - -func thing_has_method(thing, method: String, args: Array) -> bool: - if Builtins.is_supported(thing): - return thing != _autoloads - - if method in [&"call", &"call_deferred"]: - return thing.has_method(args[0]) - - if method == &"emit_signal": - return thing.has_signal(args[0]) - - if thing.has_method(method): - return true - - if method.to_snake_case() != method and DialogueSettings.has_dotnet_solution(): - # If we get this far then the method might be a C# method with a Task return type - return _get_dotnet_dialogue_manager().ThingHasMethod(thing, method) - - return false - - -# Check if a given property exists -func thing_has_property(thing: Object, property: String) -> bool: - if thing == null: - return false - - for p in thing.get_property_list(): - if _node_properties.has(p.name): - # Ignore any properties on the base Node - continue - if p.name == property: - return true - - return false - - -func resolve_signal(args: Array, extra_game_states: Array): - if args[0] is Signal: - args[0] = args[0].get_name() - - for state in get_game_states(extra_game_states): - if typeof(state) == TYPE_DICTIONARY: - continue - elif state.has_signal(args[0]): - match args.size(): - 1: - state.emit_signal(args[0]) - 2: - state.emit_signal(args[0], args[1]) - 3: - state.emit_signal(args[0], args[1], args[2]) - 4: - state.emit_signal(args[0], args[1], args[2], args[3]) - 5: - state.emit_signal(args[0], args[1], args[2], args[3], args[4]) - 6: - state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5]) - 7: - state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5], args[6]) - 8: - state.emit_signal(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]) - return - - # The signal hasn't been found anywhere - show_error_for_missing_state_value(DialogueConstants.translate(&"runtime.signal_not_found").format({ signal_name = args[0], states = str(get_game_states(extra_game_states)) })) - - -func resolve_thing_method(thing, method: String, args: Array): - if Builtins.is_supported(thing): - var result = Builtins.resolve_method(thing, method, args) - if not Builtins.has_resolve_method_failed(): - return result - - if thing.has_method(method): - # Try to convert any literals to the right type - var method_info: Dictionary = thing.get_method_list().filter(func(m): return method == m.name)[0] - var method_args: Array = method_info.args - if method_info.flags & METHOD_FLAG_VARARG == 0 and method_args.size() < args.size(): - assert(false, DialogueConstants.translate(&"runtime.expected_n_got_n_args").format({ expected = method_args.size(), method = method, received = args.size()})) - for i in range(0, args.size()): - var m: Dictionary = method_args[i] - var to_type:int = typeof(args[i]) - if m.type == TYPE_ARRAY: - match m.hint_string: - &"String": - to_type = TYPE_PACKED_STRING_ARRAY - &"int": - to_type = TYPE_PACKED_INT64_ARRAY - &"float": - to_type = TYPE_PACKED_FLOAT64_ARRAY - &"Vector2": - to_type = TYPE_PACKED_VECTOR2_ARRAY - &"Vector3": - to_type = TYPE_PACKED_VECTOR3_ARRAY - _: - if m.hint_string != "": - assert(false, DialogueConstants.translate(&"runtime.unsupported_array_type").format({ type = m.hint_string})) - if typeof(args[i]) != to_type: - args[i] = convert(args[i], to_type) - - return await thing.callv(method, args) - - # If we get here then it's probably a C# method with a Task return type - var dotnet_dialogue_manager = _get_dotnet_dialogue_manager() - dotnet_dialogue_manager.ResolveThingMethod(thing, method, args) - return await dotnet_dialogue_manager.Resolved diff --git a/addons/dialogue_manager/dialogue_reponses_menu.gd b/addons/dialogue_manager/dialogue_reponses_menu.gd deleted file mode 100644 index 6da0e5c..0000000 --- a/addons/dialogue_manager/dialogue_reponses_menu.gd +++ /dev/null @@ -1,131 +0,0 @@ -@icon("./assets/responses_menu.svg") - -## A VBoxContainer for dialogue responses provided by [b]Dialogue Manager[/b]. -class_name DialogueResponsesMenu extends VBoxContainer - - -## Emitted when a response is selected. -signal response_selected(response) - - -## Optionally specify a control to duplicate for each response -@export var response_template: Control - -## The action for accepting a response (is possibly overridden by parent dialogue balloon). -@export var next_action: StringName = &"" - -# The list of dialogue responses. -var responses: Array = []: - set(value): - responses = value - - # Remove any current items - for item in get_children(): - if item == response_template: continue - - remove_child(item) - item.queue_free() - - # Add new items - if responses.size() > 0: - for response in responses: - var item: Control - if is_instance_valid(response_template): - item = response_template.duplicate(DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_SIGNALS) - item.show() - else: - item = Button.new() - item.name = "Response%d" % get_child_count() - if not response.is_allowed: - item.name = String(item.name) + "Disallowed" - item.disabled = true - - # If the item has a response property then use that - if "response" in item: - item.response = response - # Otherwise assume we can just set the text - else: - item.text = response.text - - item.set_meta("response", response) - - add_child(item) - - _configure_focus() - - -func _ready() -> void: - visibility_changed.connect(func(): - if visible and get_menu_items().size() > 0: - get_menu_items()[0].grab_focus() - ) - - if is_instance_valid(response_template): - response_template.hide() - - -# This is deprecated. -func set_responses(next_responses: Array) -> void: - self.responses = next_responses - - -# Prepare the menu for keyboard and mouse navigation. -func _configure_focus() -> void: - var items = get_menu_items() - for i in items.size(): - var item: Control = items[i] - - item.focus_mode = Control.FOCUS_ALL - - item.focus_neighbor_left = item.get_path() - item.focus_neighbor_right = item.get_path() - - if i == 0: - item.focus_neighbor_top = item.get_path() - item.focus_previous = item.get_path() - else: - item.focus_neighbor_top = items[i - 1].get_path() - item.focus_previous = items[i - 1].get_path() - - if i == items.size() - 1: - item.focus_neighbor_bottom = item.get_path() - item.focus_next = item.get_path() - else: - item.focus_neighbor_bottom = items[i + 1].get_path() - item.focus_next = items[i + 1].get_path() - - item.mouse_entered.connect(_on_response_mouse_entered.bind(item)) - item.gui_input.connect(_on_response_gui_input.bind(item, item.get_meta("response"))) - - items[0].grab_focus() - - -## Get the selectable items in the menu. -func get_menu_items() -> Array: - var items: Array = [] - for child in get_children(): - if not child.visible: continue - if "Disallowed" in child.name: continue - items.append(child) - - return items - - -### Signals - - -func _on_response_mouse_entered(item: Control) -> void: - if "Disallowed" in item.name: return - - item.grab_focus() - - -func _on_response_gui_input(event: InputEvent, item: Control, response) -> void: - if "Disallowed" in item.name: return - - get_viewport().set_input_as_handled() - - if event is InputEventMouseButton and event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT: - response_selected.emit(response) - elif event.is_action_pressed(&"ui_accept" if next_action.is_empty() else next_action) and item in get_menu_items(): - response_selected.emit(response) diff --git a/addons/dialogue_manager/dialogue_resource.gd b/addons/dialogue_manager/dialogue_resource.gd deleted file mode 100644 index a406560..0000000 --- a/addons/dialogue_manager/dialogue_resource.gd +++ /dev/null @@ -1,42 +0,0 @@ -@tool -@icon("./assets/icon.svg") - -## A collection of dialogue lines for use with [code]DialogueManager[/code]. -class_name DialogueResource extends Resource - - -const _DialogueManager = preload("./dialogue_manager.gd") - -## A list of state shortcuts -@export var using_states: PackedStringArray = [] - -## A map of titles and the lines they point to. -@export var titles: Dictionary = {} - -## A list of character names. -@export var character_names: PackedStringArray = [] - -## The first title in the file. -@export var first_title: String = "" - -## A map of the encoded lines of dialogue. -@export var lines: Dictionary = {} - -## raw version of the text -@export var raw_text: String - - -## Get the next printable line of dialogue, starting from a referenced line ([code]title[/code] can -## be a title string or a stringified line number). Runs any mutations along the way and then returns -## the first dialogue line encountered. -func get_next_dialogue_line(title: String, extra_game_states: Array = [], mutation_behaviour: _DialogueManager.MutationBehaviour = _DialogueManager.MutationBehaviour.Wait) -> DialogueLine: - return await Engine.get_singleton("DialogueManager").get_next_dialogue_line(self, title, extra_game_states, mutation_behaviour) - - -## Get the list of any titles found in the file. -func get_titles() -> PackedStringArray: - return titles.keys() - - -func _to_string() -> String: - return "<DialogueResource titles=\"%s\">" % [",".join(titles.keys())] diff --git a/addons/dialogue_manager/dialogue_response.gd b/addons/dialogue_manager/dialogue_response.gd deleted file mode 100644 index 92cec24..0000000 --- a/addons/dialogue_manager/dialogue_response.gd +++ /dev/null @@ -1,62 +0,0 @@ -## A response to a line of dialogue, usualy attached to a [code]DialogueLine[/code]. -class_name DialogueResponse extends RefCounted - - -const _DialogueConstants = preload("./constants.gd") - - -## The ID of this response -var id: String - -## The internal type of this dialogue object, always set to [code]TYPE_RESPONSE[/code]. -var type: String = _DialogueConstants.TYPE_RESPONSE - -## The next line ID to use if this response is selected by the player. -var next_id: String = "" - -## [code]true[/code] if the condition of this line was met. -var is_allowed: bool = true - -## A character (depending on the "characters in responses" behaviour setting). -var character: String = "" - -## A dictionary of varialbe replaces for the character name. Generally for internal use only. -var character_replacements: Array[Dictionary] = [] - -## The prompt for this response. -var text: String = "" - -## A dictionary of variable replaces for the text. Generally for internal use only. -var text_replacements: Array[Dictionary] = [] - -## Any #tags -var tags: PackedStringArray = [] - -## The key to use for translating the text. -var translation_key: String = "" - - -func _init(data: Dictionary = {}) -> void: - if data.size() > 0: - id = data.id - type = data.type - next_id = data.next_id - is_allowed = data.is_allowed - character = data.character - character_replacements = data.character_replacements - text = data.text - text_replacements = data.text_replacements - tags = data.tags - translation_key = data.translation_key - - -func _to_string() -> String: - return "<DialogueResponse text=\"%s\">" % text - - -func get_tag_value(tag_name: String) -> String: - var wrapped := "%s=" % tag_name - for t in tags: - if t.begins_with(wrapped): - return t.replace(wrapped, "").strip_edges() - return "" diff --git a/addons/dialogue_manager/editor_translation_parser_plugin.gd b/addons/dialogue_manager/editor_translation_parser_plugin.gd deleted file mode 100644 index 9d404e2..0000000 --- a/addons/dialogue_manager/editor_translation_parser_plugin.gd +++ /dev/null @@ -1,43 +0,0 @@ -extends EditorTranslationParserPlugin - - -const DialogueConstants = preload("./constants.gd") -const DialogueSettings = preload("./settings.gd") -const DialogueManagerParseResult = preload("./components/parse_result.gd") - - -func _parse_file(path: String, msgids: Array, msgids_context_plural: Array) -> void: - var file: FileAccess = FileAccess.open(path, FileAccess.READ) - var text: String = file.get_as_text() - - var data: DialogueManagerParseResult = DialogueManagerParser.parse_string(text, path) - var known_keys: PackedStringArray = PackedStringArray([]) - - # Add all character names if settings ask for it - if DialogueSettings.get_setting("export_characters_in_translation", true): - var character_names: PackedStringArray = data.character_names - for character_name in character_names: - if character_name in known_keys: continue - - known_keys.append(character_name) - - msgids_context_plural.append([character_name.replace('"', '\\"'), "dialogue", ""]) - - # Add all dialogue lines and responses - var dialogue: Dictionary = data.lines - for key in dialogue.keys(): - var line: Dictionary = dialogue.get(key) - - if not line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: continue - if line.translation_key in known_keys: continue - - known_keys.append(line.translation_key) - - if line.translation_key == "" or line.translation_key == line.text: - msgids_context_plural.append([line.text.replace('"', '\\"'), "", ""]) - else: - msgids_context_plural.append([line.text.replace('"', '\\"'), line.translation_key.replace('"', '\\"'), ""]) - - -func _get_recognized_extensions() -> PackedStringArray: - return ["dialogue"] diff --git a/addons/dialogue_manager/example_balloon/ExampleBalloon.cs b/addons/dialogue_manager/example_balloon/ExampleBalloon.cs deleted file mode 100644 index a6574e0..0000000 --- a/addons/dialogue_manager/example_balloon/ExampleBalloon.cs +++ /dev/null @@ -1,204 +0,0 @@ -using Godot; -using Godot.Collections; - -namespace DialogueManagerRuntime -{ - public partial class ExampleBalloon : CanvasLayer - { - [Export] public string NextAction = "ui_accept"; - [Export] public string SkipAction = "ui_cancel"; - - - Control balloon; - RichTextLabel characterLabel; - RichTextLabel dialogueLabel; - VBoxContainer responsesMenu; - - Resource resource; - Array<Variant> temporaryGameStates = new Array<Variant>(); - bool isWaitingForInput = false; - bool willHideBalloon = false; - - DialogueLine dialogueLine; - DialogueLine DialogueLine - { - get => dialogueLine; - set - { - isWaitingForInput = false; - balloon.FocusMode = Control.FocusModeEnum.All; - balloon.GrabFocus(); - - if (value == null) - { - QueueFree(); - return; - } - - dialogueLine = value; - UpdateDialogue(); - } - } - - - public override void _Ready() - { - balloon = GetNode<Control>("%Balloon"); - characterLabel = GetNode<RichTextLabel>("%CharacterLabel"); - dialogueLabel = GetNode<RichTextLabel>("%DialogueLabel"); - responsesMenu = GetNode<VBoxContainer>("%ResponsesMenu"); - - balloon.Hide(); - - balloon.GuiInput += (@event) => - { - if ((bool)dialogueLabel.Get("is_typing")) - { - bool mouseWasClicked = @event is InputEventMouseButton && (@event as InputEventMouseButton).ButtonIndex == MouseButton.Left && @event.IsPressed(); - bool skipButtonWasPressed = @event.IsActionPressed(SkipAction); - if (mouseWasClicked || skipButtonWasPressed) - { - GetViewport().SetInputAsHandled(); - dialogueLabel.Call("skip_typing"); - return; - } - } - - if (!isWaitingForInput) return; - if (dialogueLine.Responses.Count > 0) return; - - GetViewport().SetInputAsHandled(); - - if (@event is InputEventMouseButton && @event.IsPressed() && (@event as InputEventMouseButton).ButtonIndex == MouseButton.Left) - { - Next(dialogueLine.NextId); - } - else if (@event.IsActionPressed(NextAction) && GetViewport().GuiGetFocusOwner() == balloon) - { - Next(dialogueLine.NextId); - } - }; - - if (string.IsNullOrEmpty((string)responsesMenu.Get("next_action"))) - { - responsesMenu.Set("next_action", NextAction); - } - responsesMenu.Connect("response_selected", Callable.From((DialogueResponse response) => - { - Next(response.NextId); - })); - - DialogueManager.Mutated += OnMutated; - } - - - public override void _ExitTree() - { - DialogueManager.Mutated -= OnMutated; - } - - - public override void _UnhandledInput(InputEvent @event) - { - // Only the balloon is allowed to handle input while it's showing - GetViewport().SetInputAsHandled(); - } - - - public async void Start(Resource dialogueResource, string title, Array<Variant> extraGameStates = null) - { - temporaryGameStates = extraGameStates ?? new Array<Variant>(); - isWaitingForInput = false; - resource = dialogueResource; - - DialogueLine = await DialogueManager.GetNextDialogueLine(resource, title, temporaryGameStates); - } - - - public async void Next(string nextId) - { - DialogueLine = await DialogueManager.GetNextDialogueLine(resource, nextId, temporaryGameStates); - } - - - #region Helpers - - - private async void UpdateDialogue() - { - if (!IsNodeReady()) - { - await ToSignal(this, SignalName.Ready); - } - - // Set up the character name - characterLabel.Visible = !string.IsNullOrEmpty(dialogueLine.Character); - characterLabel.Text = Tr(dialogueLine.Character, "dialogue"); - - // Set up the dialogue - dialogueLabel.Hide(); - dialogueLabel.Set("dialogue_line", dialogueLine); - - // Set up the responses - responsesMenu.Hide(); - responsesMenu.Set("responses", dialogueLine.Responses); - - // Type out the text - balloon.Show(); - willHideBalloon = false; - dialogueLabel.Show(); - if (!string.IsNullOrEmpty(dialogueLine.Text)) - { - dialogueLabel.Call("type_out"); - await ToSignal(dialogueLabel, "finished_typing"); - } - - // Wait for input - if (dialogueLine.Responses.Count > 0) - { - balloon.FocusMode = Control.FocusModeEnum.None; - responsesMenu.Show(); - } - else if (!string.IsNullOrEmpty(dialogueLine.Time)) - { - float time = 0f; - if (!float.TryParse(dialogueLine.Time, out time)) - { - time = dialogueLine.Text.Length * 0.02f; - } - await ToSignal(GetTree().CreateTimer(time), "timeout"); - Next(dialogueLine.NextId); - } - else - { - isWaitingForInput = true; - balloon.FocusMode = Control.FocusModeEnum.All; - balloon.GrabFocus(); - } - } - - - #endregion - - - #region signals - - - private void OnMutated(Dictionary _mutation) - { - isWaitingForInput = false; - willHideBalloon = true; - GetTree().CreateTimer(0.1f).Timeout += () => - { - if (willHideBalloon) - { - willHideBalloon = false; - balloon.Hide(); - } - }; - } - - - #endregion - } -} \ No newline at end of file diff --git a/addons/dialogue_manager/example_balloon/example_balloon.gd b/addons/dialogue_manager/example_balloon/example_balloon.gd deleted file mode 100644 index 875e52f..0000000 --- a/addons/dialogue_manager/example_balloon/example_balloon.gd +++ /dev/null @@ -1,141 +0,0 @@ -extends CanvasLayer - -## 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" - -@onready var balloon: Control = %Balloon -@onready var character_label: RichTextLabel = %CharacterLabel -@onready var dialogue_label: DialogueLabel = %DialogueLabel -@onready var responses_menu: DialogueResponsesMenu = %ResponsesMenu - -## 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 - -## The current line -var dialogue_line: DialogueLine: - set(next_dialogue_line): - is_waiting_for_input = false - balloon.focus_mode = Control.FOCUS_ALL - balloon.grab_focus() - - # The dialogue has finished so close the balloon - if not next_dialogue_line: - queue_free() - return - - # If the node isn't ready yet then none of the labels will be ready yet either - if not is_node_ready(): - await ready - - dialogue_line = next_dialogue_line - - 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.set_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() - get: - return dialogue_line - - -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 - - -func _unhandled_input(_event: InputEvent) -> void: - # Only the balloon is allowed to handle input while it's showing - get_viewport().set_input_as_handled() - - -## 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) - - -## 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) - - -### Signals - - -func _on_mutated(_mutation: Dictionary) -> void: - is_waiting_for_input = false - will_hide_balloon = true - get_tree().create_timer(0.1).timeout.connect(func(): - if will_hide_balloon: - will_hide_balloon = false - balloon.hide() - ) - - -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 _on_responses_menu_response_selected(response: DialogueResponse) -> void: - next(response.next_id) diff --git a/addons/dialogue_manager/example_balloon/example_balloon.tscn b/addons/dialogue_manager/example_balloon/example_balloon.tscn deleted file mode 100644 index 6facc26..0000000 --- a/addons/dialogue_manager/example_balloon/example_balloon.tscn +++ /dev/null @@ -1,149 +0,0 @@ -[gd_scene load_steps=9 format=3 uid="uid://73jm5qjy52vq"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/example_balloon/example_balloon.gd" id="1_36de5"] -[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_a8ve6"] -[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_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="ExampleBalloon" type="CanvasLayer"] -layer = 100 -script = ExtResource("1_36de5") - -[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="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("2_a8ve6")] -unique_name_in_owner = true -layout_mode = 2 -size_flags_vertical = 3 -text = "Dialogue..." - -[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" - -[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"] diff --git a/addons/dialogue_manager/example_balloon/small_example_balloon.tscn b/addons/dialogue_manager/example_balloon/small_example_balloon.tscn deleted file mode 100644 index 3011833..0000000 --- a/addons/dialogue_manager/example_balloon/small_example_balloon.tscn +++ /dev/null @@ -1,173 +0,0 @@ -[gd_scene load_steps=10 format=3 uid="uid://13s5spsk34qu"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/example_balloon/example_balloon.gd" id="1_s2gbs"] -[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_hfvdi"] -[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_menu.gd" id="3_1j1j0"] - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_235ry"] -content_margin_left = 6.0 -content_margin_top = 3.0 -content_margin_right = 6.0 -content_margin_bottom = 3.0 -bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) -border_width_left = 1 -border_width_top = 1 -border_width_right = 1 -border_width_bottom = 1 -border_color = Color(0.345098, 0.345098, 0.345098, 1) -corner_radius_top_left = 3 -corner_radius_top_right = 3 -corner_radius_bottom_right = 3 -corner_radius_bottom_left = 3 - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ufjut"] -content_margin_left = 6.0 -content_margin_top = 3.0 -content_margin_right = 6.0 -content_margin_bottom = 3.0 -bg_color = Color(0.227451, 0.227451, 0.227451, 1) -border_width_left = 1 -border_width_top = 1 -border_width_right = 1 -border_width_bottom = 1 -border_color = Color(1, 1, 1, 1) -corner_radius_top_left = 3 -corner_radius_top_right = 3 -corner_radius_bottom_right = 3 -corner_radius_bottom_left = 3 - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fcbqo"] -content_margin_left = 6.0 -content_margin_top = 3.0 -content_margin_right = 6.0 -content_margin_bottom = 3.0 -bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) -border_width_left = 1 -border_width_top = 1 -border_width_right = 1 -border_width_bottom = 1 -corner_radius_top_left = 3 -corner_radius_top_right = 3 -corner_radius_bottom_right = 3 -corner_radius_bottom_left = 3 - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_t6i7a"] -content_margin_left = 6.0 -content_margin_top = 3.0 -content_margin_right = 6.0 -content_margin_bottom = 3.0 -bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) -border_width_left = 1 -border_width_top = 1 -border_width_right = 1 -border_width_bottom = 1 -corner_radius_top_left = 3 -corner_radius_top_right = 3 -corner_radius_bottom_right = 3 -corner_radius_bottom_left = 3 - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uy0d5"] -bg_color = Color(0, 0, 0, 1) -border_width_left = 1 -border_width_top = 1 -border_width_right = 1 -border_width_bottom = 1 -corner_radius_top_left = 3 -corner_radius_top_right = 3 -corner_radius_bottom_right = 3 -corner_radius_bottom_left = 3 - -[sub_resource type="Theme" id="Theme_qq3yp"] -default_font_size = 8 -Button/styles/disabled = SubResource("StyleBoxFlat_235ry") -Button/styles/focus = SubResource("StyleBoxFlat_ufjut") -Button/styles/hover = SubResource("StyleBoxFlat_fcbqo") -Button/styles/normal = SubResource("StyleBoxFlat_t6i7a") -MarginContainer/constants/margin_bottom = 4 -MarginContainer/constants/margin_left = 8 -MarginContainer/constants/margin_right = 8 -MarginContainer/constants/margin_top = 4 -Panel/styles/panel = SubResource("StyleBoxFlat_uy0d5") - -[node name="ExampleBalloon" type="CanvasLayer"] -layer = 100 -script = ExtResource("1_s2gbs") - -[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"] -layout_mode = 1 -anchors_preset = 12 -anchor_top = 1.0 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = 3.0 -offset_top = -62.0 -offset_right = -4.0 -offset_bottom = -4.0 -grow_horizontal = 2 -grow_vertical = 0 - -[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="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("2_hfvdi")] -unique_name_in_owner = true -layout_mode = 2 -size_flags_vertical = 3 -text = "Dialogue..." -skip_pause_at_abbreviations = PackedStringArray("Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex") - -[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 = -124.0 -offset_top = -218.0 -offset_right = 125.0 -offset_bottom = -50.0 -grow_horizontal = 2 -grow_vertical = 0 - -[node name="ResponsesMenu" type="VBoxContainer" parent="Balloon/Responses"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_vertical = 8 -theme_override_constants/separation = 2 -script = ExtResource("3_1j1j0") - -[node name="ResponseExample" type="Button" parent="Balloon/Responses/ResponsesMenu"] -layout_mode = 2 -text = "Response Example" - -[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"] diff --git a/addons/dialogue_manager/import_plugin.gd b/addons/dialogue_manager/import_plugin.gd deleted file mode 100644 index 3f0af15..0000000 --- a/addons/dialogue_manager/import_plugin.gd +++ /dev/null @@ -1,113 +0,0 @@ -@tool -extends EditorImportPlugin - - -signal compiled_resource(resource: Resource) - - -const DialogueResource = preload("./dialogue_resource.gd") -const DialogueManagerParseResult = preload("./components/parse_result.gd") - -const compiler_version = 11 - - -func _get_importer_name() -> String: - # NOTE: A change to this forces a re-import of all dialogue - return "dialogue_manager_compiler_%s" % compiler_version - - -func _get_visible_name() -> String: - return "Dialogue" - - -func _get_import_order() -> int: - return -1000 - - -func _get_priority() -> float: - return 1000.0 - - -func _get_resource_type(): - return "Resource" - - -func _get_recognized_extensions() -> PackedStringArray: - return PackedStringArray(["dialogue"]) - - -func _get_save_extension(): - return "tres" - - -func _get_preset_count() -> int: - return 0 - - -func _get_preset_name(preset_index: int) -> String: - return "Unknown" - - -func _get_import_options(path: String, preset_index: int) -> Array: - # When the options array is empty there is a misleading error on export - # that actually means nothing so let's just have an invisible option. - return [{ - name = "defaults", - default_value = true - }] - - -func _get_option_visibility(path: String, option_name: StringName, options: Dictionary) -> bool: - return false - - -func _import(source_file: String, save_path: String, options: Dictionary, platform_variants: Array[String], gen_files: Array[String]) -> Error: - var cache = Engine.get_meta("DialogueCache") - - # Get the raw file contents - if not FileAccess.file_exists(source_file): return ERR_FILE_NOT_FOUND - - var file: FileAccess = FileAccess.open(source_file, FileAccess.READ) - var raw_text: String = file.get_as_text() - - # Parse the text - var parser: DialogueManagerParser = DialogueManagerParser.new() - var err: Error = parser.parse(raw_text, source_file) - var data: DialogueManagerParseResult = parser.get_data() - var errors: Array[Dictionary] = parser.get_errors() - parser.free() - - if err != OK: - printerr("%d errors found in %s" % [errors.size(), source_file]) - cache.add_errors_to_file(source_file, errors) - return err - - # Get the current addon version - var config: ConfigFile = ConfigFile.new() - config.load("res://addons/dialogue_manager/plugin.cfg") - var version: String = config.get_value("plugin", "version") - - # Save the results to a resource - var resource: DialogueResource = DialogueResource.new() - resource.set_meta("dialogue_manager_version", version) - - resource.using_states = data.using_states - resource.titles = data.titles - resource.first_title = data.first_title - resource.character_names = data.character_names - resource.lines = data.lines - resource.raw_text = data.raw_text - - # Clear errors and possibly trigger any cascade recompiles - cache.add_file(source_file, data) - - err = ResourceSaver.save(resource, "%s.%s" % [save_path, _get_save_extension()]) - - compiled_resource.emit(resource) - - # Recompile any dependencies - var dependent_paths: PackedStringArray = cache.get_dependent_paths_for_reimport(source_file) - for path in dependent_paths: - append_import_external_resource(path) - - return err diff --git a/addons/dialogue_manager/l10n/en.mo b/addons/dialogue_manager/l10n/en.mo deleted file mode 100644 index 2ab4fdfdac7d7f52d3d107052e417714a09b6bdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9770 zcmb7|e~=|tRmU654>HjZFn|zEZYJRF#>`8yQCViQEZLdeWZ3Kvc4m`+N~h;_&rE0D z>wa|io7u@YBoHBGiKz+{1qJ^S!Lm$QT1xy;VkL@2Sx~i>f5Z~8fI_eo3$c`xTG7w< z{&=t7>_B1HJMY`~++XLOd(OG{^jBVe*+(OuC!n8%mM)8;-v>YR3jTN=x;lz}6imQt z!2<jV@KNwJ;KxCJ(KGyA1O5^CdhiS2kAYtY)$ZTGSA$nF7*j-V0AB~*2;K<38T@hZ z0nc9tUrYIMQ2jmuYMkE&uLGY4CGQKM=KBxuX7H6v`Udb$Q0-2G*MnV;kAmv=Nnigg zC^^0e-T;0Bd=+>Zi;+C91=ar+Q2kDTny>3|2fT^$$3TtqhaNA2>i18e<i7lsPQL3w z$#)c#9^d85wJ$&E%by168a)SU9T!3A{~tlg_dSnS!BqKr5LPq;UI88f)qft;Iu?EX zsxNPXY)SNMzWgyzdj2g?<NT@Te+lFleT_d<9R0iJYf`P_I#B&?12yk4P<mJZC3gZ| z1#W<v?=evN`jD@G29%u7gBtIzJ$@UM-d@4rw}Ll-(&tG~dRqngMUU~P^?d|X|4)Oe ze-6}s{hcqr2pY<-qVb!+gB~9QHUE1-+1sy!lJip_B1FIA%g=$*%a=g4{|d;E(YHZ< zcCnK8Iu@;Vw}5h?Sy1E5fd)JeO3n@Njo?$D^zjFv`oG}o|J9eTf{95+H-eIT2Ba!l z1f}OSQ1<v3sC9n=)IR+lsD1l0Q2j50lJ_5c{dax+|AJcgwfw1mAE@@TpaJg%wZ0tG zygQ)w;lrTje+FcT=<}fT@@4RfmqpP(gO^kOE{(MRFM`s;%MnuTt^*YZZU(2o{h;Q* z6V!T6fLDSKfm+WRsP;pUp`%B@JHV$v`Tg^r|4nc|<(ELow~xWJA4kD`;2BW;H$6TH z{uJe>L9Oq3Q1ZP1PJ`bB?*gaTv|GS?K=rRc?ccA0Ocgx?N-uxu%U=f%Q~n=N?GI5Y zJ)ZH{1^Gpr{7Ek#@%S_-eSQ{{++PGG-`|6h@4rFm=~|3i<(om35Bc&*Q2ibPwT=OJ z7x*Z61pE_F`us0Y^Ipl|iodT1<-czMrT4diYIiRvJ3jBr?*?Tb>%P1N%3nSRs@;b@ z|C6Bh{WGBK;CDU$Sx|cT3sC+37L@$o@c1Gq`L8AzOOES7wYwR-4ZIDMK4Y*0Zh$Ai zr$O1nzkmn98(7qx;5$I^KL8#AKMOKN^c|3<(KW{DWya$=DE<E?DE)j6{8{iKsQy>r ztiq$9^m_r+I8T7ukKX`g&wmWcUOx{?FMkDUJ%0mgJzoZ;$8UN5e}Y=~OQ70cgYl{T z>%gA@Zv=l1JPH0h_&#ty_^ijTf{#<4!WnJ{p9D4k=RmeP`g8Ck_*L*>a0cVmd>{At z8BlioEU36~5tMvi^Y|T5_V5y@bzV&{Qhx(V54VGo^C-wKTIcW0;8URX_Y0t1H>mdC z^7uUvk)kVpI*MKf>XCg&X6@qzNRQPC_?QYjk2|n3XrJ`F4SGAI`91)xK@1;lLbApC zAnEWukRAi=KpT+OJb-FQ&wC;HLj|os;gJr{Ko3CggMJA*0O|Q4^eEI<!9Of3`Vr_M z=-rTXAD(-8xyu*s4opyb{uOBGdD~zH{Q~q>=ocY9=ONj)9_^L%xC+TW2^02_uQbp+ z^n~SH`ga%>ValFEggYB2<RkY$%g`)z3-lUD&pITZn1gPG-U7WJ3XlBmGAM=Q8+w+Y z%OTmwBaj~1sh&mXgne_iRq&2`TKn<r=(K<7dVC|;gB0Um4jqSPptI0Bp<|Hz=M?k~ zsDxyH3s3^x4^2aQI*@E%&rt_9)=c^L2R**aqd>kFLpih$+JfYl=b&GPM$htaWhJXR z-CkK|QM(W)z1}3FY}T?WUdek|J*p@NTb2_Kl4dP%>ttgzmfquJ)S+H0H{-l;qioep z){nYnv65H)*oiPv>ZEzyO{#RVO~;O(mfbqas;aE&PSUHgB;AVh{-CUyEDd}HOY<f# zi+C-m<D!gVG+EJv`gAzx<=v#o;(XMn#j~Sb+P2A?UKZF{f6#2j6D(<n$(nej92TQ- zooum_IP}hoZrLC7G9<_@463ZI5q4a;k@WKPhpJ(&DyI2xBv@X!-g%L-;zU~5J+P`S z>}J}f#Ko|`oK<_*)lHQbtD)}UVSf-eC7bHzn^47iwsol{dU=6K6lvUNy~*lG;(pHZ zi&bj~!sROIu4kjo3f1GSDl!Zxom9RPfA8%c7AQIEs!zgHt3|(M3$4oKvg~EaNL}rk zNs(GLvfe#}Znr3V<1Lur_xnlE<^<mx?;dq&IZ{ijM}|(zl|AgG)n;W_blbMjs+!#M zRz*3;s-!7L=FqB|w1rm1MpEU;^4L#?#d=Y0wsdNX6MLt)P<N|*5Y`rN=FM8XJj{D( zWW!F}%j>4YYlCgBW`)GcU}8^sT1Vc+R;rR{Qg1|gQD;@-p_ABk)5>x?$q=JW(v76( zW`URHNv~YRhkP3;bT?1-9_lNsn7JgtXk5>0vJ0b`@#{g!tf5=ImaJ#-@^ZIKM?50o zpvP)P<2XO^f;3wL8P^~gjz{sldXQny-L<5^lYH|{1zkUWA(JQ~_OKwzXGs-TSr@za zf!y+mjF&Q1W4pzPZ5vg?qRIPNC#kB0SgYU>m%~QmFDug3qZT&E#c9?gd2f=rt4$r( zS>_v#t3oJgg~TxTWIzerUbfN@;@Pb_e<X{$Nult&tb<2xt{72{<mhM3TAA9g)a8t` zMj8fc)w$puDq3epi^ay4!wUNeyg?;j;XoLN|4=1ClHOhwrDoOkZfaXLtCHXvdU>~r zHLP{PaYa2GxYI6n8{%Yd^&B@yb8GuawMER;>i2B*o+0*E6*?|`D|dMJdfrxS5lbTo z(y&(4mz!C3c*nrHYn^`5bl2DithII=LT?k^Ip{X>a#)9Qm0|j5(Kq!)djZ+SQa}jJ znsRlOgLbmBJqNAt)mhV^R88VutjG7tBpq|wYr$`89FWzwx^#zigM;Ii4WWsEGw#cF zmQ@yqQ>o^N&D;sx>d*P!8>U&jf+JvsArQ1$g#H-z_u<CahE(TQQDmFQ<ATMQYp-9U zHs}{C)c&N|N;2&6y2lEv$n~z_Ju@85qai(?`&-p?hfPb?%_<qh9Br#U4%#c8x4npN z2$IB-S|L2Lf{bFS4RZBFSZ~@JF&w0*wUcb1KkKNTk#dx1D`QuVcCp#_z;c=orM!+u zV_8!P1BC_!!L(+dteyB#DP>r)T$k`XW@>&yO*iXtMl}tG`($0YzBivB@i4cL(7GOW zyIh2#vyMHpkj~tXcVURLX5Jr2=2TK}Q>v!Uo|!p^^Qd-a9@Wg6sr!<;nOX8$D=W(> zR);j7S;~@rt2}GcZ0gj)spI1b?&#b;HRmqHGfP_o#*_2hhCk-TVI%**0*;(tIx%x- z+)i_mG|U|5_L`#WS#xMPZ>G-nhE>v=IZ;;qde#&JTda>9JZ#+Sk^P0a>4>@Gz~QL} zXYO&Qx8yxrX57-vot=Z7gHzF*%|z_KQ3~STZ0=#~B_Nt3>9DWHTK%H34gHy<?sPiQ zA}NN+3v&W<TXZRgt#wCaZJN^T+g8t=eMh5tpJ23GMDt25)ExnAVqrpJ(TVOhqol&< z+&9)@Oj0nVF4|e@*vps@Vl<s-X)UkK!o1->3|AI(a7)q{ooGHJB7P=QBpkGK&8n>3 zF)`L-jN+ha){-VPR7z4Cckr3z%-FP~;}*e8#-3(jz=T0v9wI$)_SB;VTD^9n1(%m# zU}k&>ccSB?97RI;V_L24)xXu0`6^@6k#TJ+5t(FOK(1Z#uOgRSV`AK`wB5v%MQ=;n z!1V$}_6D5%!+uufU2CxJa6-YU?^|o#$g7*1<Q|j+RLoYEVE4^QZ#CPAPG(zXdYf>( zGi_R$JFZOApzv+&*v_qHyIb~#{bFa<Z2Mrj6P<DyjPc2U@fnPt-<k{a`;f1>7v|dw z({${eOKa4L>D+#k&mfFlGd9*C9Bk3hS+v_gt;I|qd8;{odVabSogbw-ctuEcCfGj7 zndG_jW`cLgT3SP+g0h%wU6Rb~;`lUXf=dE3QRb#?%9WM{P1J^@Wr7(Dqa{zcB~7$* zDar&ZBqw6pJjB#nSQCaA%H9~>Sq{ybLd)1)wz%;bm!@=xF&9vO*0<Ki3*J<1nPe5i z>_qCU=pZ{=p<y`n!eGl8UXmFGl;aw1c6zVOs`Y*150@+-@_e++Tx?mGucHO~al(~D zWK-f}<`(Z)6kKq*&)q)hxtnaqgls3AD$#MY9;AxiF8837U3zrRrZ#r`Iuz`^>Rd=> z7L~=AW5?!{#Vn1|mnHjkgtJ5*<`NcPu$hWC+UNmk)py>uxx|hPV7n=sq_;!V=h|po zQsQ-Rx|}SZQAWc`h1kB%23Ac{Vn*W)8;$9b6TR7sGTv=*2RFG-5!`un+mE$#cH41s zlAfKgV}u*KLqTWuuyh;!!#6jJS!T`*n*q`(Ou96QAT_-`j<p0IB837%qBxqTE!RL& zYmPg6$1272@r9q&jte`}(S4*!tc{JY^E8|Exz_m+5+@8og1LO4EmTOIjH@ChGgG;& ziw(2v)nnW+DYmSU8+WNR`?uZ8&H*}VAMMvfX4@6^B1~YU`jC4Wu2UN<C6$~Z|7uGb zcoOmZ&#c}dMZ^Ev132~%?j9|MEY2v4Gd7DGhm&z&n&VC*&j=cdb<#7N70w%IUKjfs zGfLk&(GTj>-s}Hg$8o-gt?io8-KTmz?|b2T<T5{d>97|mA8c&3j<+`RlyX2!iX8B? zlE1Sd>pSPuJ&*R57v6Q~&qkreqRkzxm)O{|7;-wonZ2QNAt4_bANyW1JfM|E_%+Pg zTn?A5(XDbhv%e1u$KsQ4YK|dj2#ia#SyYn)(c*eOFeT~K=-9Tl>Ml1SF6@`160A7< z7%EE-5QuEz2h)A}soizPWh3J&WF0MW!E8ojx20A_$l>khh!$4tNuj&jP+uCY^Kj+4 zq>DX<2uJpYqkB(QD0NDafc;#{dILMq3PIQUgWoq@HgpszkjWU5l!Xv|5JRWJR>pyS zI@=sOpd3}pVo;mqxfO=g)P~0BY(l<H!a_ExL3}pa+Jh+1I)<~V;rqRU(X{+%QMq)d z<}D7+J8fkn8uwD}aqJo&!p!t!6RC)ER3G+a915Ue>GmG2)!BnKBYBZHdBbJUeX+?| zih`mGQf{~Swk2&?J(hMtb#OOxE21IQ@Y(PKB*8{Wus<;u-N%_r61a$t=z?o4s<cOz zY;B}eUD$Q%+cQ|k(fTN{v5gv)`0bcc4oj-y5@F*~&runnbvC*LViPM$v{KBVZ$irJ z>;r3ZId<fePV**i_OuTvw>zW!G&gBPjifm5Qy&z`UDTz_?y|#INDlFyZbqZg&uN2w lCarTVtC5u*F#70OVIy|S{K&hD!7oD^?9RqbGge6_`aihw)SUnT diff --git a/addons/dialogue_manager/l10n/en.po b/addons/dialogue_manager/l10n/en.po deleted file mode 100644 index bf844cb..0000000 --- a/addons/dialogue_manager/l10n/en.po +++ /dev/null @@ -1,481 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Dialogue Manager\n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: \n" -"Language-Team: \n" -"Language: de\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.2.2\n" - -msgid "start_a_new_file" -msgstr "Start a new file" - -msgid "open_a_file" -msgstr "Open a file" - -msgid "open.open" -msgstr "Open..." - -msgid "open.no_recent_files" -msgstr "No recent files" - -msgid "open.clear_recent_files" -msgstr "Clear recent files" - -msgid "save_all_files" -msgstr "Save all files" - -msgid "find_in_files" -msgstr "Find in files..." - -msgid "test_dialogue" -msgstr "Test dialogue" - -msgid "search_for_text" -msgstr "Search for text" - -msgid "insert" -msgstr "Insert" - -msgid "translations" -msgstr "Translations" - -msgid "settings" -msgstr "Settings" - -msgid "sponsor" -msgstr "Sponsor" - -msgid "show_support" -msgstr "Support Dialogue Manager" - -msgid "docs" -msgstr "Docs" - -msgid "insert.wave_bbcode" -msgstr "Wave BBCode" - -msgid "insert.shake_bbcode" -msgstr "Shake BBCode" - -msgid "insert.typing_pause" -msgstr "Typing pause" - -msgid "insert.typing_speed_change" -msgstr "Typing speed change" - -msgid "insert.auto_advance" -msgstr "Auto advance" - -msgid "insert.templates" -msgstr "Templates" - -msgid "insert.title" -msgstr "Title" - -msgid "insert.dialogue" -msgstr "Dialogue" - -msgid "insert.response" -msgstr "Response" - -msgid "insert.random_lines" -msgstr "Random lines" - -msgid "insert.random_text" -msgstr "Random text" - -msgid "insert.actions" -msgstr "Actions" - -msgid "insert.jump" -msgstr "Jump to title" - -msgid "insert.end_dialogue" -msgstr "End dialogue" - -msgid "generate_line_ids" -msgstr "Generate line IDs" - -msgid "save_characters_to_csv" -msgstr "Save character names to CSV..." - -msgid "save_to_csv" -msgstr "Save lines to CSV..." - -msgid "import_from_csv" -msgstr "Import line changes from CSV..." - -msgid "confirm_close" -msgstr "Save changes to '{path}'?" - -msgid "confirm_close.save" -msgstr "Save changes" - -msgid "confirm_close.discard" -msgstr "Discard" - -msgid "buffer.save" -msgstr "Save" - -msgid "buffer.save_as" -msgstr "Save as..." - -msgid "buffer.close" -msgstr "Close" - -msgid "buffer.close_all" -msgstr "Close all" - -msgid "buffer.close_other_files" -msgstr "Close other files" - -msgid "buffer.copy_file_path" -msgstr "Copy file path" - -msgid "buffer.show_in_filesystem" -msgstr "Show in FileSystem" - -msgid "settings.invalid_test_scene" -msgstr "\"{path}\" does not extend BaseDialogueTestScene." - -msgid "settings.revert_to_default_test_scene" -msgstr "Revert to default test scene" - -msgid "settings.default_balloon_hint" -msgstr "Custom balloon to use when calling \"DialogueManager.show_balloon()\"" - -msgid "settings.revert_to_default_balloon" -msgstr "Revert to default balloon" - -msgid "settings.default_balloon_path" -msgstr "<example balloon>" - -msgid "settings.autoload" -msgstr "Autoload" - -msgid "settings.path" -msgstr "Path" - -msgid "settings.new_template" -msgstr "New dialogue files will start with template text" - -msgid "settings.missing_keys" -msgstr "Treat missing translation keys as errors" - -msgid "settings.missing_keys_hint" -msgstr "If you are using static translation keys then having this enabled will help you find any lines that you haven't added a key to yet." - -msgid "settings.characters_translations" -msgstr "Export character names in translation files" - -msgid "settings.wrap_long_lines" -msgstr "Wrap long lines" - -msgid "settings.include_failed_responses" -msgstr "Include responses with failed conditions" - -msgid "settings.ignore_missing_state_values" -msgstr "Skip over missing state value errors (not recommended)" - -msgid "settings.custom_test_scene" -msgstr "Custom test scene (must extend BaseDialogueTestScene)" - -msgid "settings.default_csv_locale" -msgstr "Default CSV Locale" - -msgid "settings.states_shortcuts" -msgstr "State Shortcuts" - -msgid "settings.states_message" -msgstr "If an autoload is enabled here you can refer to its properties and methods without having to use its name." - -msgid "settings.states_hint" -msgstr "ie. Instead of \"SomeState.some_property\" you could just use \"some_property\"" - -msgid "settings.recompile_warning" -msgstr "Changing these settings will force a recompile of all dialogue. Only change them if you know what you are doing." - -msgid "settings.create_lines_for_responses_with_characters" -msgstr "Create child dialogue line for responses with character names in them" - -msgid "settings.open_in_external_editor" -msgstr "Open dialogue files in external editor" - -msgid "settings.external_editor_warning" -msgstr "Note: Syntax highlighting and detailed error checking are not supported in external editors." - -msgid "settings.include_characters_in_translations" -msgstr "Include character names in translation exports" - -msgid "settings.include_notes_in_translations" -msgstr "Include notes (## comments) in translation exports" - -msgid "settings.check_for_updates" -msgstr "Check for updates" - -msgid "n_of_n" -msgstr "{index} of {total}" - -msgid "search.find" -msgstr "Find:" - -msgid "search.find_all" -msgstr "Find all..." - -msgid "search.placeholder" -msgstr "Text to search for" - -msgid "search.replace_placeholder" -msgstr "Text to replace it with" - -msgid "search.replace_selected" -msgstr "Replace selected" - -msgid "search.previous" -msgstr "Previous" - -msgid "search.next" -msgstr "Next" - -msgid "search.match_case" -msgstr "Match case" - -msgid "search.toggle_replace" -msgstr "Replace" - -msgid "search.replace_with" -msgstr "Replace with:" - -msgid "search.replace" -msgstr "Replace" - -msgid "search.replace_all" -msgstr "Replace all" - -msgid "files_list.filter" -msgstr "Filter files" - -msgid "titles_list.filter" -msgstr "Filter titles" - -msgid "errors.key_not_found" -msgstr "Key \"{key}\" not found." - -msgid "errors.line_and_message" -msgstr "Error at {line}, {column}: {message}" - -msgid "errors_in_script" -msgstr "You have errors in your script. Fix them and then try again." - -msgid "errors_with_build" -msgstr "You need to fix dialogue errors before you can run your game." - -msgid "errors.import_errors" -msgstr "There are errors in this imported file." - -msgid "errors.already_imported" -msgstr "File already imported." - -msgid "errors.duplicate_import" -msgstr "Duplicate import name." - -msgid "errors.unknown_using" -msgstr "Unknown autoload in using statement." - -msgid "errors.empty_title" -msgstr "Titles cannot be empty." - -msgid "errors.duplicate_title" -msgstr "There is already a title with that name." - -msgid "errors.nested_title" -msgstr "Titles cannot be indented." - -msgid "errors.invalid_title_string" -msgstr "Titles can only contain alphanumeric characters and numbers." - -msgid "errors.invalid_title_number" -msgstr "Titles cannot begin with a number." - -msgid "errors.unknown_title" -msgstr "Unknown title." - -msgid "errors.jump_to_invalid_title" -msgstr "This jump is pointing to an invalid title." - -msgid "errors.title_has_no_content" -msgstr "That title has no content. Maybe change this to a \"=> END\"." - -msgid "errors.invalid_expression" -msgstr "Expression is invalid." - -msgid "errors.unexpected_condition" -msgstr "Unexpected condition." - -msgid "errors.duplicate_id" -msgstr "This ID is already on another line." - -msgid "errors.missing_id" -msgstr "This line is missing an ID." - -msgid "errors.invalid_indentation" -msgstr "Invalid indentation." - -msgid "errors.condition_has_no_content" -msgstr "A condition line needs an indented line below it." - -msgid "errors.incomplete_expression" -msgstr "Incomplete expression." - -msgid "errors.invalid_expression_for_value" -msgstr "Invalid expression for value." - -msgid "errors.file_not_found" -msgstr "File not found." - -msgid "errors.unexpected_end_of_expression" -msgstr "Unexpected end of expression." - -msgid "errors.unexpected_function" -msgstr "Unexpected function." - -msgid "errors.unexpected_bracket" -msgstr "Unexpected bracket." - -msgid "errors.unexpected_closing_bracket" -msgstr "Unexpected closing bracket." - -msgid "errors.missing_closing_bracket" -msgstr "Missing closing bracket." - -msgid "errors.unexpected_operator" -msgstr "Unexpected operator." - -msgid "errors.unexpected_comma" -msgstr "Unexpected comma." - -msgid "errors.unexpected_colon" -msgstr "Unexpected colon." - -msgid "errors.unexpected_dot" -msgstr "Unexpected dot." - -msgid "errors.unexpected_boolean" -msgstr "Unexpected boolean." - -msgid "errors.unexpected_string" -msgstr "Unexpected string." - -msgid "errors.unexpected_number" -msgstr "Unexpected number." - -msgid "errors.unexpected_variable" -msgstr "Unexpected variable." - -msgid "errors.invalid_index" -msgstr "Invalid index." - -msgid "errors.unexpected_assignment" -msgstr "Unexpected assignment." - -msgid "errors.unknown" -msgstr "Unknown syntax." - -msgid "update.available" -msgstr "v{version} available" - -msgid "update.is_available_for_download" -msgstr "Version %s is available for download!" - -msgid "update.downloading" -msgstr "Downloading..." - -msgid "update.download_update" -msgstr "Download update" - -msgid "update.needs_reload" -msgstr "The project needs to be reloaded to install the update." - -msgid "update.reload_ok_button" -msgstr "Reload project" - -msgid "update.reload_cancel_button" -msgstr "Do it later" - -msgid "update.reload_project" -msgstr "Reload project" - -msgid "update.release_notes" -msgstr "Read release notes" - -msgid "update.success" -msgstr "Dialogue Manager is now v{version}." - -msgid "update.failed" -msgstr "There was a problem downloading the update." - -msgid "runtime.no_resource" -msgstr "No dialogue resource provided." - -msgid "runtime.no_content" -msgstr "\"{file_path}\" has no content." - -msgid "runtime.errors" -msgstr "You have {count} errors in your dialogue text." - -msgid "runtime.error_detail" -msgstr "Line {line}: {message}" - -msgid "runtime.errors_see_details" -msgstr "You have {count} errors in your dialogue text. See Output for details." - -msgid "runtime.invalid_expression" -msgstr "\"{expression}\" is not a valid expression: {error}" - -msgid "runtime.array_index_out_of_bounds" -msgstr "Index {index} out of bounds of array \"{array}\"." - -msgid "runtime.left_hand_size_cannot_be_assigned_to" -msgstr "Left hand side of expression cannot be assigned to." - -msgid "runtime.key_not_found" -msgstr "Key \"{key}\" not found in dictionary \"{dictionary}\"" - -msgid "runtime.property_not_found" -msgstr "\"{property}\" is not a property on any game states ({states})." - -msgid "runtime.property_not_found_missing_export" -msgstr "\"{property}\" is not a property on any game states ({states}). You might need to add an [Export] decorator." - -msgid "runtime.method_not_found" -msgstr "\"{method}\" is not a method on any game states ({states})" - -msgid "runtime.signal_not_found" -msgstr "\"{signal_name}\" is not a signal on any game states ({states})" - -msgid "runtime.method_not_callable" -msgstr "\"{method}\" is not a callable method on \"{object}\"" - -msgid "runtime.unknown_operator" -msgstr "Unknown operator." - -msgid "runtime.unknown_autoload" -msgstr "\"{autoload}\" doesn't appear to be a valid autoload." - -msgid "runtime.something_went_wrong" -msgstr "Something went wrong." - -msgid "runtime.expected_n_got_n_args" -msgstr "\"{method}\" was called with {received} arguments but it only has {expected}." - -msgid "runtime.unsupported_array_type" -msgstr "Array[{type}] isn't supported in mutations. Use Array as a type instead." - -msgid "runtime.dialogue_balloon_missing_start_method" -msgstr "Your dialogue balloon is missing a \"start\" or \"Start\" method." \ No newline at end of file diff --git a/addons/dialogue_manager/l10n/es.po b/addons/dialogue_manager/l10n/es.po deleted file mode 100644 index 3cbaa32..0000000 --- a/addons/dialogue_manager/l10n/es.po +++ /dev/null @@ -1,457 +0,0 @@ -# -msgid "" -msgstr "" -"Project-Id-Version: Dialogue Manager\n" -"POT-Creation-Date: 2024-02-25 20:58\n" -"PO-Revision-Date: 2024-02-25 20:58\n" -"Last-Translator: you <you@example.com>\n" -"Language-Team: Spanish <yourteam@example.com>\n" -"Language: es\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" - -msgid "start_a_new_file" -msgstr "Crear un nuevo archivo" - -msgid "open_a_file" -msgstr "Abrir un archivo" - -msgid "open.open" -msgstr "Abrir..." - -msgid "open.no_recent_files" -msgstr "No hay archivos recientes" - -msgid "open.clear_recent_files" -msgstr "Limpiar archivos recientes" - -msgid "save_all_files" -msgstr "Guardar todos los archivos" - -msgid "test_dialogue" -msgstr "Diálogo de prueba" - -msgid "search_for_text" -msgstr "Buscar texto" - -msgid "insert" -msgstr "Insertar" - -msgid "translations" -msgstr "Traducciones" - -msgid "settings" -msgstr "Ajustes" - -msgid "show_support" -msgstr "Contribuye con Dialogue Manager" - -msgid "docs" -msgstr "Docs" - -msgid "insert.wave_bbcode" -msgstr "BBCode ondulado" - -msgid "insert.shake_bbcode" -msgstr "BBCode agitado" - -msgid "insert.typing_pause" -msgstr "Pausa de escritura" - -msgid "insert.typing_speed_change" -msgstr "Cambiar la velocidad de escritura" - -msgid "insert.auto_advance" -msgstr "Avance automático" - -msgid "insert.templates" -msgstr "Plantillas" - -msgid "insert.title" -msgstr "Título" - -msgid "insert.dialogue" -msgstr "Diálogo" - -msgid "insert.response" -msgstr "Respuesta" - -msgid "insert.random_lines" -msgstr "Líneas aleatorias" - -msgid "insert.random_text" -msgstr "Texto aleatorio" - -msgid "insert.actions" -msgstr "Acciones" - -msgid "insert.jump" -msgstr "Ir al título" - -msgid "insert.end_dialogue" -msgstr "Finalizar diálogo" - -msgid "generate_line_ids" -msgstr "Generar IDs de línea" - -msgid "save_characters_to_csv" -msgstr "Guardar los nombres de los personajes en un archivo CSV..." - -msgid "save_to_csv" -msgstr "Guardar líneas en CSV..." - -msgid "import_from_csv" -msgstr "Importar cambios de línea desde CSV..." - -msgid "confirm_close" -msgstr "¿Guardar los cambios en '{path}'?" - -msgid "confirm_close.save" -msgstr "Guardar cambios" - -msgid "confirm_close.discard" -msgstr "Descartar" - -msgid "buffer.save" -msgstr "Guardar" - -msgid "buffer.save_as" -msgstr "Guardar como..." - -msgid "buffer.close" -msgstr "Cerrar" - -msgid "buffer.close_all" -msgstr "Cerrar todo" - -msgid "buffer.close_other_files" -msgstr "Cerrar otros archivos" - -msgid "buffer.copy_file_path" -msgstr "Copiar la ruta del archivo" - -msgid "buffer.show_in_filesystem" -msgstr "Mostrar en el sistema de archivos" - -msgid "settings.invalid_test_scene" -msgstr "\"{path}\" no extiende BaseDialogueTestScene." - -msgid "settings.revert_to_default_test_scene" -msgstr "Revertir a la escena de prueba por defecto" - -msgid "settings.default_balloon_hint" -msgstr "" -"Globo personalizado para usar al llamar a \"DialogueManager.show_balloon()\"" - -msgid "settings.revert_to_default_balloon" -msgstr "Volver al globo predeterminado" - -msgid "settings.default_balloon_path" -msgstr "<globo de ejemplo>" - -msgid "settings.autoload" -msgstr "Autocarga" - -msgid "settings.path" -msgstr "Ruta" - -msgid "settings.new_template" -msgstr "Los nuevos archivos de diálogo empezarán con una plantilla" - -msgid "settings.missing_keys" -msgstr "Tratar las claves de traducción faltantes como errores" - -msgid "settings.missing_keys_hint" -msgstr "Si estás utilizando claves de traducción estáticas, tener esta opción habilitada te ayudará a encontrar cualquier línea a la que aún no le hayas añadido una clave." - -msgid "settings.characters_translations" -msgstr "Exportar nombres de personajes en archivos de traducción" - -msgid "settings.wrap_long_lines" -msgstr "Romper líneas largas" - -msgid "settings.include_failed_responses" -msgstr "Incluir respuestas con condiciones fallidas" - -msgid "settings.ignore_missing_state_values" -msgstr "Omitir errores de valores de estado faltantes (no recomendado)" - -msgid "settings.custom_test_scene" -msgstr "Escena de prueba personalizada (debe extender BaseDialogueTestScene)" - -msgid "settings.default_csv_locale" -msgstr "Localización CSV por defecto" - -msgid "settings.states_shortcuts" -msgstr "Atajos de teclado" - -msgid "settings.states_message" -msgstr "Si un autoload está habilitado aquí, puedes referirte a sus propiedades y métodos sin tener que usar su nombre." - -msgid "settings.states_hint" -msgstr "ie. En lugar de \"SomeState.some_property\" podría simplemente usar \"some_property\"" - -msgid "settings.recompile_warning" -msgstr "Cambiar estos ajustes obligará a recompilar todo el diálogo. Hazlo solo si sabes lo que estás haciendo." - -msgid "settings.create_lines_for_responses_with_characters" -msgstr "Crear línea de diálogo para respuestas con nombres de personajes dentro." - -msgid "settings.open_in_external_editor" -msgstr "Abrir archivos de diálogo en el editor externo" - -msgid "settings.external_editor_warning" -msgstr "Nota: El resaltado de sintaxis y la verificación detallada de errores no están soportados en editores externos." - -msgid "settings.include_characters_in_translations" -msgstr "Incluir nombres de personajes en las exportaciones de traducción" - -msgid "settings.include_notes_in_translations" -msgstr "Incluir notas (## comentarios) en las exportaciones de traducción" - -msgid "n_of_n" -msgstr "{index} de {total}" - -msgid "search.previous" -msgstr "Anterior" - -msgid "search.next" -msgstr "Siguiente" - -msgid "search.match_case" -msgstr "Coincidir mayúsculas/minúsculas" - -msgid "search.toggle_replace" -msgstr "Reemplazar" - -msgid "search.replace_with" -msgstr "Reemplazar con:" - -msgid "search.replace" -msgstr "Reemplazar" - -msgid "search.replace_all" -msgstr "Reemplazar todo" - -msgid "files_list.filter" -msgstr "Filtrar archivos" - -msgid "titles_list.filter" -msgstr "Filtrar títulos" - -msgid "errors.key_not_found" -msgstr "La tecla \"{key}\" no se encuentra." - -msgid "errors.line_and_message" -msgstr "Error en {line}, {column}: {message}" - -msgid "errors_in_script" -msgstr "Tienes errores en tu guion. Corrígelos y luego inténtalo de nuevo." - -msgid "errors_with_build" -msgstr "Debes corregir los errores de diálogo antes de poder ejecutar tu juego." - -msgid "errors.import_errors" -msgstr "Hay errores en este archivo importado." - -msgid "errors.already_imported" -msgstr "Archivo ya importado." - -msgid "errors.duplicate_import" -msgstr "Nombre de importación duplicado." - -msgid "errors.unknown_using" -msgstr "Autoload desconocida en la declaración de uso." - -msgid "errors.empty_title" -msgstr "Los títulos no pueden estar vacíos." - -msgid "errors.duplicate_title" -msgstr "Ya hay un título con ese nombre." - -msgid "errors.nested_title" -msgstr "Los títulos no pueden tener sangría." - -msgid "errors.invalid_title_string" -msgstr "Los títulos solo pueden contener caracteres alfanuméricos y números." - -msgid "errors.invalid_title_number" -msgstr "Los títulos no pueden empezar con un número." - -msgid "errors.unknown_title" -msgstr "Título desconocido." - -msgid "errors.jump_to_invalid_title" -msgstr "Este salto está apuntando a un título inválido." - -msgid "errors.title_has_no_content" -msgstr "Ese título no tiene contenido. Quizá cambiarlo a \"=> FIN\"." - -msgid "errors.invalid_expression" -msgstr "La expresión es inválida." - -msgid "errors.unexpected_condition" -msgstr "Condición inesperada." - -msgid "errors.duplicate_id" -msgstr "Este ID ya está en otra línea." - -msgid "errors.missing_id" -msgstr "Esta línea está sin ID." - -msgid "errors.invalid_indentation" -msgstr "Sangría no válida." - -msgid "errors.condition_has_no_content" -msgstr "Una línea de condición necesita una línea sangrada debajo de ella." - -msgid "errors.incomplete_expression" -msgstr "Expresión incompleta." - -msgid "errors.invalid_expression_for_value" -msgstr "Expresión no válida para valor." - -msgid "errors.file_not_found" -msgstr "Archivo no encontrado." - -msgid "errors.unexpected_end_of_expression" -msgstr "Fin de expresión inesperado." - -msgid "errors.unexpected_function" -msgstr "Función inesperada." - -msgid "errors.unexpected_bracket" -msgstr "Corchete inesperado." - -msgid "errors.unexpected_closing_bracket" -msgstr "Bracket de cierre inesperado." - -msgid "errors.missing_closing_bracket" -msgstr "Falta cerrar corchete." - -msgid "errors.unexpected_operator" -msgstr "Operador inesperado." - -msgid "errors.unexpected_comma" -msgstr "Coma inesperada." - -msgid "errors.unexpected_colon" -msgstr "Dos puntos inesperados" - -msgid "errors.unexpected_dot" -msgstr "Punto inesperado." - -msgid "errors.unexpected_boolean" -msgstr "Booleano inesperado." - -msgid "errors.unexpected_string" -msgstr "String inesperado." - -msgid "errors.unexpected_number" -msgstr "Número inesperado." - -msgid "errors.unexpected_variable" -msgstr "Variable inesperada." - -msgid "errors.invalid_index" -msgstr "Índice no válido." - -msgid "errors.unexpected_assignment" -msgstr "Asignación inesperada." - -msgid "errors.unknown" -msgstr "Sintaxis desconocida." - -msgid "update.available" -msgstr "v{version} disponible" - -msgid "update.is_available_for_download" -msgstr "¡La versión %s ya está disponible para su descarga!" - -msgid "update.downloading" -msgstr "Descargando..." - -msgid "update.download_update" -msgstr "Descargar actualización" - -msgid "update.needs_reload" -msgstr "El proyecto debe ser recargado para instalar la actualización." - -msgid "update.reload_ok_button" -msgstr "Recargar proyecto" - -msgid "update.reload_cancel_button" -msgstr "Hazlo más tarde" - -msgid "update.reload_project" -msgstr "Recargar proyecto" - -msgid "update.release_notes" -msgstr "Leer las notas de la versión" - -msgid "update.success" -msgstr "El Gestor de Diálogo ahora es v{versión}." - -msgid "update.failed" -msgstr "Hubo un problema al descargar la actualización." - -msgid "runtime.no_resource" -msgstr "Recurso de diálogo no proporcionado." - -msgid "runtime.no_content" -msgstr "\"{file_path}\" no tiene contenido." - -msgid "runtime.errors" -msgstr "Tienes {count} errores en tu diálogo de texto." - -msgid "runtime.error_detail" -msgstr "Línea {line}: {message}" - -msgid "runtime.errors_see_details" -msgstr "Tienes {count} errores en tu texto de diálogo. Consulta la salida para más detalles." - -msgid "runtime.invalid_expression" -msgstr "\"{expression}\" no es una expresión válida: {error}" - -msgid "runtime.array_index_out_of_bounds" -msgstr "Índice {index} fuera de los límites del array \"{array}\"." - -msgid "runtime.left_hand_size_cannot_be_assigned_to" -msgstr "El lado izquierdo de la expresión no se puede asignar." - -msgid "runtime.key_not_found" -msgstr "Clave \"{key}\" no encontrada en el diccionario \"{dictionary}\"" - -msgid "runtime.property_not_found" -msgstr "\"{property}\" no es una propiedad en ningún estado del juego ({states})." - -msgid "runtime.property_not_found_missing_export" -msgstr "\"{property}\" no es una propiedad en ningún estado del juego ({states}). Es posible que necesites añadir un decorador [Export]." - -msgid "runtime.method_not_found" -msgstr "\"{method}\" no es un método en ningún estado del juego ({states})" - -msgid "runtime.signal_not_found" -msgstr "\"{signal_name}\" no es una señal en ningún estado del juego ({states})" - -msgid "runtime.method_not_callable" -msgstr "\"{method}\" no es un método llamable en \"{object}\"" - -msgid "runtime.unknown_operator" -msgstr "Operador desconocido." - -msgid "runtime.unknown_autoload" -msgstr "\"{autoload}\" parece no ser un autoload válido." - -msgid "runtime.something_went_wrong" -msgstr "Algo salió mal." - -msgid "runtime.expected_n_got_n_args" -msgstr "El método \"{method}\" se llamó con {received} argumentos, pero solo tiene {expected}." - -msgid "runtime.unsupported_array_type" -msgstr "Array[{type}] no está soportado en mutaciones. Utiliza Array como tipo en su lugar." - -msgid "runtime.dialogue_balloon_missing_start_method" -msgstr "Tu globo de diálogo no tiene un método \"start\" o \"Start\"." diff --git a/addons/dialogue_manager/l10n/translations.pot b/addons/dialogue_manager/l10n/translations.pot deleted file mode 100644 index 4aeec3b..0000000 --- a/addons/dialogue_manager/l10n/translations.pot +++ /dev/null @@ -1,471 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Dialogue Manager\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8-bit\n" - -msgid "start_a_new_file" -msgstr "" - -msgid "open_a_file" -msgstr "" - -msgid "open.open" -msgstr "" - -msgid "open.no_recent_files" -msgstr "" - -msgid "open.clear_recent_files" -msgstr "" - -msgid "save_all_files" -msgstr "" - -msgid "find_in_files" -msgstr "" - -msgid "test_dialogue" -msgstr "" - -msgid "search_for_text" -msgstr "" - -msgid "insert" -msgstr "" - -msgid "translations" -msgstr "" - -msgid "settings" -msgstr "" - -msgid "sponsor" -msgstr "" - -msgid "show_support" -msgstr "" - -msgid "docs" -msgstr "" - -msgid "insert.wave_bbcode" -msgstr "" - -msgid "insert.shake_bbcode" -msgstr "" - -msgid "insert.typing_pause" -msgstr "" - -msgid "insert.typing_speed_change" -msgstr "" - -msgid "insert.auto_advance" -msgstr "" - -msgid "insert.templates" -msgstr "" - -msgid "insert.title" -msgstr "" - -msgid "insert.dialogue" -msgstr "" - -msgid "insert.response" -msgstr "" - -msgid "insert.random_lines" -msgstr "" - -msgid "insert.random_text" -msgstr "" - -msgid "insert.actions" -msgstr "" - -msgid "insert.jump" -msgstr "" - -msgid "insert.end_dialogue" -msgstr "" - -msgid "generate_line_ids" -msgstr "" - -msgid "save_to_csv" -msgstr "" - -msgid "import_from_csv" -msgstr "" - -msgid "confirm_close" -msgstr "" - -msgid "confirm_close.save" -msgstr "" - -msgid "confirm_close.discard" -msgstr "" - -msgid "buffer.save" -msgstr "" - -msgid "buffer.save_as" -msgstr "" - -msgid "buffer.close" -msgstr "" - -msgid "buffer.close_all" -msgstr "" - -msgid "buffer.close_other_files" -msgstr "" - -msgid "buffer.copy_file_path" -msgstr "" - -msgid "buffer.show_in_filesystem" -msgstr "" - -msgid "settings.invalid_test_scene" -msgstr "" - -msgid "settings.revert_to_default_test_scene" -msgstr "" - -msgid "settings.default_balloon_hint" -msgstr "" - -msgid "settings.revert_to_default_balloon" -msgstr "" - -msgid "settings.default_balloon_path" -msgstr "" - -msgid "settings.autoload" -msgstr "" - -msgid "settings.path" -msgstr "" - -msgid "settings.new_template" -msgstr "" - -msgid "settings.missing_keys" -msgstr "" - -msgid "settings.missing_keys_hint" -msgstr "" - -msgid "settings.characters_translations" -msgstr "" - -msgid "settings.wrap_long_lines" -msgstr "" - -msgid "settings.include_failed_responses" -msgstr "" - -msgid "settings.ignore_missing_state_values" -msgstr "" - -msgid "settings.custom_test_scene" -msgstr "" - -msgid "settings.default_csv_locale" -msgstr "" - -msgid "settings.states_shortcuts" -msgstr "" - -msgid "settings.states_message" -msgstr "" - -msgid "settings.states_hint" -msgstr "" - -msgid "settings.recompile_warning" -msgstr "" - -msgid "settings.create_lines_for_responses_with_characters" -msgstr "" - -msgid "settings.open_in_external_editor" -msgstr "" - -msgid "settings.external_editor_warning" -msgstr "" - -msgid "settings.include_characters_in_translations" -msgstr "" - -msgid "settings.include_notes_in_translations" -msgstr "" - -msgid "settings.check_for_updates" -msgstr "" - -msgid "n_of_n" -msgstr "" - -msgid "search.find" -msgstr "" - -msgid "search.find_all" -msgstr "" - -msgid "search.placeholder" -msgstr "" - -msgid "search.replace_placeholder" -msgstr "" - -msgid "search.replace_selected" -msgstr "" - -msgid "search.previous" -msgstr "" - -msgid "search.next" -msgstr "" - -msgid "search.match_case" -msgstr "" - -msgid "search.toggle_replace" -msgstr "" - -msgid "search.replace_with" -msgstr "" - -msgid "search.replace" -msgstr "" - -msgid "search.replace_all" -msgstr "" - -msgid "files_list.filter" -msgstr "" - -msgid "titles_list.filter" -msgstr "" - -msgid "errors.key_not_found" -msgstr "" - -msgid "errors.line_and_message" -msgstr "" - -msgid "errors_in_script" -msgstr "" - -msgid "errors_with_build" -msgstr "" - -msgid "errors.import_errors" -msgstr "" - -msgid "errors.already_imported" -msgstr "" - -msgid "errors.duplicate_import" -msgstr "" - -msgid "errors.unknown_using" -msgstr "" - -msgid "errors.empty_title" -msgstr "" - -msgid "errors.duplicate_title" -msgstr "" - -msgid "errors.nested_title" -msgstr "" - -msgid "errors.invalid_title_string" -msgstr "" - -msgid "errors.invalid_title_number" -msgstr "" - -msgid "errors.unknown_title" -msgstr "" - -msgid "errors.jump_to_invalid_title" -msgstr "" - -msgid "errors.title_has_no_content" -msgstr "" - -msgid "errors.invalid_expression" -msgstr "" - -msgid "errors.unexpected_condition" -msgstr "" - -msgid "errors.duplicate_id" -msgstr "" - -msgid "errors.missing_id" -msgstr "" - -msgid "errors.invalid_indentation" -msgstr "" - -msgid "errors.condition_has_no_content" -msgstr "" - -msgid "errors.incomplete_expression" -msgstr "" - -msgid "errors.invalid_expression_for_value" -msgstr "" - -msgid "errors.file_not_found" -msgstr "" - -msgid "errors.unexpected_end_of_expression" -msgstr "" - -msgid "errors.unexpected_function" -msgstr "" - -msgid "errors.unexpected_bracket" -msgstr "" - -msgid "errors.unexpected_closing_bracket" -msgstr "" - -msgid "errors.missing_closing_bracket" -msgstr "" - -msgid "errors.unexpected_operator" -msgstr "" - -msgid "errors.unexpected_comma" -msgstr "" - -msgid "errors.unexpected_colon" -msgstr "" - -msgid "errors.unexpected_dot" -msgstr "" - -msgid "errors.unexpected_boolean" -msgstr "" - -msgid "errors.unexpected_string" -msgstr "" - -msgid "errors.unexpected_number" -msgstr "" - -msgid "errors.unexpected_variable" -msgstr "" - -msgid "errors.invalid_index" -msgstr "" - -msgid "errors.unexpected_assignment" -msgstr "" - -msgid "errors.unknown" -msgstr "" - -msgid "update.available" -msgstr "" - -msgid "update.is_available_for_download" -msgstr "" - -msgid "update.downloading" -msgstr "" - -msgid "update.download_update" -msgstr "" - -msgid "update.needs_reload" -msgstr "" - -msgid "update.reload_ok_button" -msgstr "" - -msgid "update.reload_cancel_button" -msgstr "" - -msgid "update.reload_project" -msgstr "" - -msgid "update.release_notes" -msgstr "" - -msgid "update.success" -msgstr "" - -msgid "update.failed" -msgstr "" - -msgid "runtime.no_resource" -msgstr "" - -msgid "runtime.no_content" -msgstr "" - -msgid "runtime.errors" -msgstr "" - -msgid "runtime.error_detail" -msgstr "" - -msgid "runtime.errors_see_details" -msgstr "" - -msgid "runtime.invalid_expression" -msgstr "" - -msgid "runtime.array_index_out_of_bounds" -msgstr "" - -msgid "runtime.left_hand_size_cannot_be_assigned_to" -msgstr "" - -msgid "runtime.key_not_found" -msgstr "" - -msgid "runtime.property_not_found" -msgstr "" - -msgid "runtime.property_not_found_missing_export" -msgstr "" - -msgid "runtime.method_not_found" -msgstr "" - -msgid "runtime.signal_not_found" -msgstr "" - -msgid "runtime.method_not_callable" -msgstr "" - -msgid "runtime.unknown_operator" -msgstr "" - -msgid "runtime.unknown_autoload" -msgstr "" - -msgid "runtime.something_went_wrong" -msgstr "" - -msgid "runtime.expected_n_got_n_args" -msgstr "" - -msgid "runtime.unsupported_array_type" -msgstr "" - -msgid "runtime.dialogue_balloon_missing_start_method" -msgstr "" \ No newline at end of file diff --git a/addons/dialogue_manager/l10n/zh.po b/addons/dialogue_manager/l10n/zh.po deleted file mode 100644 index b7f032f..0000000 --- a/addons/dialogue_manager/l10n/zh.po +++ /dev/null @@ -1,408 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Dialogue Manager\n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: \n" -"Language-Team: penghao123456、憨憨羊の宇航鸽鸽\n" -"Language: zh\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 3.4\n" - -msgid "start_a_new_file" -msgstr "创建新文件" - -msgid "open_a_file" -msgstr "打开已有文件" - -msgid "open.open" -msgstr "打开……" - -msgid "open.no_recent_files" -msgstr "无历史记录" - -msgid "open.clear_recent_files" -msgstr "清空历史记录" - -msgid "save_all_files" -msgstr "保存所有文件" - -msgid "test_dialogue" -msgstr "测试对话" - -msgid "search_for_text" -msgstr "查找……" - -msgid "insert" -msgstr "插入" - -msgid "translations" -msgstr "翻译" - -msgid "settings" -msgstr "设置" - -msgid "show_support" -msgstr "支持 Dialogue Manager" - -msgid "docs" -msgstr "文档" - -msgid "insert.wave_bbcode" -msgstr "BBCode [lb]wave[rb]" - -msgid "insert.shake_bbcode" -msgstr "BBCode [lb]wave[rb]" - -msgid "insert.typing_pause" -msgstr "输入间隔" - -msgid "insert.typing_speed_change" -msgstr "输入速度变更" - -msgid "insert.auto_advance" -msgstr "自动切行" - -msgid "insert.templates" -msgstr "模板" - -msgid "insert.title" -msgstr "标题" - -msgid "insert.dialogue" -msgstr "对话" - -msgid "insert.response" -msgstr "回复选项" - -msgid "insert.random_lines" -msgstr "随机行" - -msgid "insert.random_text" -msgstr "随机文本" - -msgid "insert.actions" -msgstr "操作" - -msgid "insert.jump" -msgstr "标题间跳转" - -msgid "insert.end_dialogue" -msgstr "结束对话" - -msgid "generate_line_ids" -msgstr "生成行 ID" - -msgid "save_to_csv" -msgstr "生成 CSV" - -msgid "import_from_csv" -msgstr "从 CSV 导入" - -msgid "confirm_close" -msgstr "是否要保存到“{path}”?" - -msgid "confirm_close.save" -msgstr "保存" - -msgid "confirm_close.discard" -msgstr "不保存" - -msgid "buffer.save" -msgstr "保存" - -msgid "buffer.save_as" -msgstr "另存为……" - -msgid "buffer.close" -msgstr "关闭" - -msgid "buffer.close_all" -msgstr "全部关闭" - -msgid "buffer.close_other_files" -msgstr "关闭其他文件" - -msgid "buffer.copy_file_path" -msgstr "复制文件路径" - -msgid "buffer.show_in_filesystem" -msgstr "在 Godot 侧边栏中显示" - -msgid "settings.revert_to_default_test_scene" -msgstr "重置测试场景设定" - -msgid "settings.autoload" -msgstr "Autoload" - -msgid "settings.path" -msgstr "路径" - -msgid "settings.new_template" -msgstr "新建文件时自动插入模板" - -msgid "settings.missing_keys" -msgstr "将翻译键缺失视为错误" - -msgid "settings.missing_keys_hint" -msgstr "如果你使用静态键,这将会帮助你寻找未添加至翻译文件的键。" - -msgid "settings.characters_translations" -msgstr "在翻译文件中导出角色名。" - -msgid "settings.wrap_long_lines" -msgstr "自动折行" - -msgid "settings.include_failed_responses" -msgstr "在判断条件失败时仍显示回复选项" - -msgid "settings.ignore_missing_state_values" -msgstr "忽略全局变量缺失错误(不建议)" - -msgid "settings.custom_test_scene" -msgstr "自定义测试场景(必须继承自BaseDialogueTestScene)" - -msgid "settings.default_csv_locale" -msgstr "默认 CSV 区域格式" - -msgid "settings.states_shortcuts" -msgstr "全局变量映射" - -msgid "settings.states_message" -msgstr "当一个 Autoload 在这里被勾选,他的所有成员会被映射为全局变量。" - -msgid "settings.states_hint" -msgstr "比如,当你开启对于“Foo”的映射时,你可以将“Foo.bar”简写成“bar”。" - -msgid "n_of_n" -msgstr "第{index}个,共{total}个" - -msgid "search.previous" -msgstr "查找上一个" - -msgid "search.next" -msgstr "查找下一个" - -msgid "search.match_case" -msgstr "大小写敏感" - -msgid "search.toggle_replace" -msgstr "替换" - -msgid "search.replace_with" -msgstr "替换为" - -msgid "search.replace" -msgstr "替换" - -msgid "search.replace_all" -msgstr "全部替换" - -msgid "files_list.filter" -msgstr "查找文件" - -msgid "titles_list.filter" -msgstr "查找标题" - -msgid "errors.key_not_found" -msgstr "键“{key}”未找到" - -msgid "errors.line_and_message" -msgstr "第{line}行第{colume}列发生错误:{message}" - -msgid "errors_in_script" -msgstr "你的脚本中存在错误。请修复错误,然后重试。" - -msgid "errors_with_build" -msgstr "请先解决 Dialogue 中的错误。" - -msgid "errors.import_errors" -msgstr "被导入的文件存在问题。" - -msgid "errors.already_imported" -msgstr "文件已被导入。" - -msgid "errors.duplicate_import" -msgstr "导入名不能重复。" - -msgid "errors.empty_title" -msgstr "标题名不能为空。" - -msgid "errors.duplicate_title" -msgstr "标题名不能重复。" - -msgid "errors.nested_title" -msgstr "标题不能嵌套。" - -msgid "errors.invalid_title_string" -msgstr "标题名无效。" - -msgid "errors.invalid_title_number" -msgstr "标题不能以数字开始。" - -msgid "errors.unknown_title" -msgstr "标题未定义。" - -msgid "errors.jump_to_invalid_title" -msgstr "标题名无效。" - -msgid "errors.title_has_no_content" -msgstr "目标标题为空。请替换为“=> END”。" - -msgid "errors.invalid_expression" -msgstr "表达式无效。" - -msgid "errors.unexpected_condition" -msgstr "未知条件。" - -msgid "errors.duplicate_id" -msgstr "ID 重复。" - -msgid "errors.missing_id" -msgstr "ID 不存在。" - -msgid "errors.invalid_indentation" -msgstr "缩进无效。" - -msgid "errors.condition_has_no_content" -msgstr "条件下方不能为空。" - -msgid "errors.incomplete_expression" -msgstr "不完整的表达式。" - -msgid "errors.invalid_expression_for_value" -msgstr "无效的赋值表达式。" - -msgid "errors.file_not_found" -msgstr "文件不存在。" - -msgid "errors.unexpected_end_of_expression" -msgstr "表达式 end 不应存在。" - -msgid "errors.unexpected_function" -msgstr "函数不应存在。" - -msgid "errors.unexpected_bracket" -msgstr "方括号不应存在。" - -msgid "errors.unexpected_closing_bracket" -msgstr "方括号不应存在。" - -msgid "errors.missing_closing_bracket" -msgstr "闭方括号不存在。" - -msgid "errors.unexpected_operator" -msgstr "操作符不应存在。" - -msgid "errors.unexpected_comma" -msgstr "逗号不应存在。" - -msgid "errors.unexpected_colon" -msgstr "冒号不应存在。" - -msgid "errors.unexpected_dot" -msgstr "句号不应存在。" - -msgid "errors.unexpected_boolean" -msgstr "布尔值不应存在。" - -msgid "errors.unexpected_string" -msgstr "字符串不应存在。" - -msgid "errors.unexpected_number" -msgstr "数字不应存在。" - -msgid "errors.unexpected_variable" -msgstr "标识符不应存在。" - -msgid "errors.invalid_index" -msgstr "索引无效。" - -msgid "errors.unexpected_assignment" -msgstr "不应在条件判断中使用 = ,应使用 == 。" - -msgid "errors.unknown" -msgstr "语法错误。" - -msgid "update.available" -msgstr "v{version} 更新可用。" - -msgid "update.is_available_for_download" -msgstr "v%s 已经可以下载。" - -msgid "update.downloading" -msgstr "正在下载更新……" - -msgid "update.download_update" -msgstr "下载" - -msgid "update.needs_reload" -msgstr "需要重新加载项目以应用更新。" - -msgid "update.reload_ok_button" -msgstr "重新加载" - -msgid "update.reload_cancel_button" -msgstr "暂不重新加载" - -msgid "update.reload_project" -msgstr "重新加载" - -msgid "update.release_notes" -msgstr "查看发行注记" - -msgid "update.success" -msgstr "v{version} 已成功安装并应用。" - -msgid "update.failed" -msgstr "更新失败。" - -msgid "runtime.no_resource" -msgstr "找不到资源。" - -msgid "runtime.no_content" -msgstr "资源“{file_path}”为空。" - -msgid "runtime.errors" -msgstr "文件中存在{errrors}个错误。" - -msgid "runtime.error_detail" -msgstr "第{index}行:{message}" - -msgid "runtime.errors_see_details" -msgstr "文件中存在{errrors}个错误。请查看调试输出。" - -msgid "runtime.invalid_expression" -msgstr "表达式“{expression}”无效:{error}" - -msgid "runtime.array_index_out_of_bounds" -msgstr "数组索引“{index}”越界。(数组名:“{array}”)" - -msgid "runtime.left_hand_size_cannot_be_assigned_to" -msgstr "表达式左侧的变量无法被赋值。" - -msgid "runtime.key_not_found" -msgstr "键“{key}”在字典“{dictionary}”中不存在。" - -msgid "runtime.property_not_found" -msgstr "“{property}”不存在。(全局变量:{states})" - -msgid "runtime.property_not_found_missing_export" -msgstr "“{property}”不存在。(全局变量:{states})你可能需要添加一个修饰词 [Export]。" - -msgid "runtime.method_not_found" -msgstr "“{method}”不存在。(全局变量:{states})" - -msgid "runtime.signal_not_found" -msgstr "“{sighal_name}”不存在。(全局变量:{states})" - -msgid "runtime.method_not_callable" -msgstr "{method}不是对象“{object}”上的函数。" - -msgid "runtime.unknown_operator" -msgstr "未知操作符。" - -msgid "runtime.something_went_wrong" -msgstr "有什么出错了。" diff --git a/addons/dialogue_manager/l10n/zh_TW.po b/addons/dialogue_manager/l10n/zh_TW.po deleted file mode 100644 index 3bcf153..0000000 --- a/addons/dialogue_manager/l10n/zh_TW.po +++ /dev/null @@ -1,408 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Dialogue Manager\n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: \n" -"Language-Team: 憨憨羊の宇航鴿鴿\n" -"Language: zh_TW\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 3.4\n" - -msgid "start_a_new_file" -msgstr "創建新檔案" - -msgid "open_a_file" -msgstr "開啟已有檔案" - -msgid "open.open" -msgstr "開啟……" - -msgid "open.no_recent_files" -msgstr "無歷史記錄" - -msgid "open.clear_recent_files" -msgstr "清空歷史記錄" - -msgid "save_all_files" -msgstr "儲存所有檔案" - -msgid "test_dialogue" -msgstr "測試對話" - -msgid "search_for_text" -msgstr "搜尋……" - -msgid "insert" -msgstr "插入" - -msgid "translations" -msgstr "翻譯" - -msgid "settings" -msgstr "設定" - -msgid "show_support" -msgstr "支援 Dialogue Manager" - -msgid "docs" -msgstr "文檔" - -msgid "insert.wave_bbcode" -msgstr "BBCode [lb]wave[rb]" - -msgid "insert.shake_bbcode" -msgstr "BBCode [lb]wave[rb]" - -msgid "insert.typing_pause" -msgstr "輸入間隔" - -msgid "insert.typing_speed_change" -msgstr "輸入速度變更" - -msgid "insert.auto_advance" -msgstr "自動切行" - -msgid "insert.templates" -msgstr "模板" - -msgid "insert.title" -msgstr "標題" - -msgid "insert.dialogue" -msgstr "對話" - -msgid "insert.response" -msgstr "回覆選項" - -msgid "insert.random_lines" -msgstr "隨機行" - -msgid "insert.random_text" -msgstr "隨機文本" - -msgid "insert.actions" -msgstr "操作" - -msgid "insert.jump" -msgstr "標題間跳轉" - -msgid "insert.end_dialogue" -msgstr "結束對話" - -msgid "generate_line_ids" -msgstr "生成行 ID" - -msgid "save_to_csv" -msgstr "生成 CSV" - -msgid "import_from_csv" -msgstr "從 CSV 匯入" - -msgid "confirm_close" -msgstr "是否要儲存到“{path}”?" - -msgid "confirm_close.save" -msgstr "儲存" - -msgid "confirm_close.discard" -msgstr "不儲存" - -msgid "buffer.save" -msgstr "儲存" - -msgid "buffer.save_as" -msgstr "儲存爲……" - -msgid "buffer.close" -msgstr "關閉" - -msgid "buffer.close_all" -msgstr "全部關閉" - -msgid "buffer.close_other_files" -msgstr "關閉其他檔案" - -msgid "buffer.copy_file_path" -msgstr "複製檔案位置" - -msgid "buffer.show_in_filesystem" -msgstr "在 Godot 側邊欄中顯示" - -msgid "settings.revert_to_default_test_scene" -msgstr "重置測試場景設定" - -msgid "settings.autoload" -msgstr "Autoload" - -msgid "settings.path" -msgstr "路徑" - -msgid "settings.new_template" -msgstr "新建檔案時自動插入模板" - -msgid "settings.missing_keys" -msgstr "將翻譯鍵缺失視爲錯誤" - -msgid "settings.missing_keys_hint" -msgstr "如果你使用靜態鍵,這將會幫助你尋找未添加至翻譯檔案的鍵。" - -msgid "settings.wrap_long_lines" -msgstr "自動折行" - -msgid "settings.characters_translations" -msgstr "在翻譯檔案中匯出角色名。" - -msgid "settings.include_failed_responses" -msgstr "在判斷條件失敗時仍顯示回復選項" - -msgid "settings.ignore_missing_state_values" -msgstr "忽略全局變量缺失錯誤(不建議)" - -msgid "settings.custom_test_scene" -msgstr "自訂測試場景(必須繼承自BaseDialogueTestScene)" - -msgid "settings.default_csv_locale" -msgstr "預設 CSV 區域格式" - -msgid "settings.states_shortcuts" -msgstr "全局變量映射" - -msgid "settings.states_message" -msgstr "當一個 Autoload 在這裏被勾選,他的所有成員會被映射爲全局變量。" - -msgid "settings.states_hint" -msgstr "比如,當你開啓對於“Foo”的映射時,你可以將“Foo.bar”簡寫成“bar”。" - -msgid "n_of_n" -msgstr "第{index}個,共{total}個" - -msgid "search.previous" -msgstr "搜尋上一個" - -msgid "search.next" -msgstr "搜尋下一個" - -msgid "search.match_case" -msgstr "大小寫敏感" - -msgid "search.toggle_replace" -msgstr "替換" - -msgid "search.replace_with" -msgstr "替換爲" - -msgid "search.replace" -msgstr "替換" - -msgid "search.replace_all" -msgstr "全部替換" - -msgid "files_list.filter" -msgstr "搜尋檔案" - -msgid "titles_list.filter" -msgstr "搜尋標題" - -msgid "errors.key_not_found" -msgstr "鍵“{key}”未找到" - -msgid "errors.line_and_message" -msgstr "第{line}行第{colume}列發生錯誤:{message}" - -msgid "errors_in_script" -msgstr "你的腳本中存在錯誤。請修復錯誤,然後重試。" - -msgid "errors_with_build" -msgstr "請先解決 Dialogue 中的錯誤。" - -msgid "errors.import_errors" -msgstr "被匯入的檔案存在問題。" - -msgid "errors.already_imported" -msgstr "檔案已被匯入。" - -msgid "errors.duplicate_import" -msgstr "匯入名不能重複。" - -msgid "errors.empty_title" -msgstr "標題名不能爲空。" - -msgid "errors.duplicate_title" -msgstr "標題名不能重複。" - -msgid "errors.nested_title" -msgstr "標題不能嵌套。" - -msgid "errors.invalid_title_string" -msgstr "標題名無效。" - -msgid "errors.invalid_title_number" -msgstr "標題不能以數字開始。" - -msgid "errors.unknown_title" -msgstr "標題未定義。" - -msgid "errors.jump_to_invalid_title" -msgstr "標題名無效。" - -msgid "errors.title_has_no_content" -msgstr "目標標題爲空。請替換爲“=> END”。" - -msgid "errors.invalid_expression" -msgstr "表達式無效。" - -msgid "errors.unexpected_condition" -msgstr "未知條件。" - -msgid "errors.duplicate_id" -msgstr "ID 重複。" - -msgid "errors.missing_id" -msgstr "ID 不存在。" - -msgid "errors.invalid_indentation" -msgstr "縮進無效。" - -msgid "errors.condition_has_no_content" -msgstr "條件下方不能爲空。" - -msgid "errors.incomplete_expression" -msgstr "不完整的表達式。" - -msgid "errors.invalid_expression_for_value" -msgstr "無效的賦值表達式。" - -msgid "errors.file_not_found" -msgstr "檔案不存在。" - -msgid "errors.unexpected_end_of_expression" -msgstr "表達式 end 不應存在。" - -msgid "errors.unexpected_function" -msgstr "函數不應存在。" - -msgid "errors.unexpected_bracket" -msgstr "方括號不應存在。" - -msgid "errors.unexpected_closing_bracket" -msgstr "方括號不應存在。" - -msgid "errors.missing_closing_bracket" -msgstr "閉方括號不存在。" - -msgid "errors.unexpected_operator" -msgstr "操作符不應存在。" - -msgid "errors.unexpected_comma" -msgstr "逗號不應存在。" - -msgid "errors.unexpected_colon" -msgstr "冒號不應存在。" - -msgid "errors.unexpected_dot" -msgstr "句號不應存在。" - -msgid "errors.unexpected_boolean" -msgstr "布爾值不應存在。" - -msgid "errors.unexpected_string" -msgstr "字符串不應存在。" - -msgid "errors.unexpected_number" -msgstr "數字不應存在。" - -msgid "errors.unexpected_variable" -msgstr "標識符不應存在。" - -msgid "errors.invalid_index" -msgstr "索引無效。" - -msgid "errors.unexpected_assignment" -msgstr "不應在條件判斷中使用 = ,應使用 == 。" - -msgid "errors.unknown" -msgstr "語法錯誤。" - -msgid "update.available" -msgstr "v{version} 更新可用。" - -msgid "update.is_available_for_download" -msgstr "v%s 已經可以下載。" - -msgid "update.downloading" -msgstr "正在下載更新……" - -msgid "update.download_update" -msgstr "下載" - -msgid "update.needs_reload" -msgstr "需要重新加載項目以套用更新。" - -msgid "update.reload_ok_button" -msgstr "重新加載" - -msgid "update.reload_cancel_button" -msgstr "暫不重新加載" - -msgid "update.reload_project" -msgstr "重新加載" - -msgid "update.release_notes" -msgstr "查看發行註記" - -msgid "update.success" -msgstr "v{version} 已成功安裝並套用。" - -msgid "update.failed" -msgstr "更新失敗。" - -msgid "runtime.no_resource" -msgstr "找不到資源。" - -msgid "runtime.no_content" -msgstr "資源“{file_path}”爲空。" - -msgid "runtime.errors" -msgstr "檔案中存在{errrors}個錯誤。" - -msgid "runtime.error_detail" -msgstr "第{index}行:{message}" - -msgid "runtime.errors_see_details" -msgstr "檔案中存在{errrors}個錯誤。請查看調試輸出。" - -msgid "runtime.invalid_expression" -msgstr "表達式“{expression}”無效:{error}" - -msgid "runtime.array_index_out_of_bounds" -msgstr "數組索引“{index}”越界。(數組名:“{array}”)" - -msgid "runtime.left_hand_size_cannot_be_assigned_to" -msgstr "表達式左側的變量無法被賦值。" - -msgid "runtime.key_not_found" -msgstr "鍵“{key}”在字典“{dictionary}”中不存在。" - -msgid "runtime.property_not_found" -msgstr "“{property}”不存在。(全局變量:{states})" - -msgid "runtime.method_not_found" -msgstr "“{method}”不存在。(全局變量:{states})" - -msgid "runtime.signal_not_found" -msgstr "“{sighal_name}”不存在。(全局變量:{states})" - -msgid "runtime.property_not_found_missing_export" -msgstr "“{property}”不存在。(全局變量:{states})你可能需要添加一個修飾詞 [Export]。" - -msgid "runtime.method_not_callable" -msgstr "{method}不是對象“{object}”上的函數。" - -msgid "runtime.unknown_operator" -msgstr "未知操作符。" - -msgid "runtime.something_went_wrong" -msgstr "有什麼出錯了。" diff --git a/addons/dialogue_manager/plugin.cfg b/addons/dialogue_manager/plugin.cfg deleted file mode 100644 index 572ad9f..0000000 --- a/addons/dialogue_manager/plugin.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[plugin] - -name="Dialogue Manager" -description="A simple but powerful branching dialogue system" -author="Nathan Hoad" -version="2.38.0" -script="plugin.gd" diff --git a/addons/dialogue_manager/plugin.gd b/addons/dialogue_manager/plugin.gd deleted file mode 100644 index 70836f3..0000000 --- a/addons/dialogue_manager/plugin.gd +++ /dev/null @@ -1,276 +0,0 @@ -@tool -extends EditorPlugin - - -const DialogueConstants = preload("./constants.gd") -const DialogueImportPlugin = preload("./import_plugin.gd") -const DialogueTranslationParserPlugin = preload("./editor_translation_parser_plugin.gd") -const DialogueSettings = preload("./settings.gd") -const DialogueCache = preload("./components/dialogue_cache.gd") -const MainView = preload("./views/main_view.tscn") - - -var import_plugin: DialogueImportPlugin -var translation_parser_plugin: DialogueTranslationParserPlugin -var main_view -var dialogue_cache: DialogueCache - - -func _enter_tree() -> void: - add_autoload_singleton("DialogueManager", get_plugin_path() + "/dialogue_manager.gd") - - if Engine.is_editor_hint(): - Engine.set_meta("DialogueManagerPlugin", self) - - DialogueSettings.prepare() - - import_plugin = DialogueImportPlugin.new() - add_import_plugin(import_plugin) - - translation_parser_plugin = DialogueTranslationParserPlugin.new() - add_translation_parser_plugin(translation_parser_plugin) - - main_view = MainView.instantiate() - main_view.editor_plugin = self - get_editor_interface().get_editor_main_screen().add_child(main_view) - _make_visible(false) - - dialogue_cache = DialogueCache.new() - main_view.add_child(dialogue_cache) - Engine.set_meta("DialogueCache", dialogue_cache) - - _update_localization() - - get_editor_interface().get_file_system_dock().files_moved.connect(_on_files_moved) - get_editor_interface().get_file_system_dock().file_removed.connect(_on_file_removed) - - add_tool_menu_item("Create copy of dialogue example balloon...", _copy_dialogue_balloon) - - # Prevent the project from showing as unsaved even though it was only just opened - if Engine.get_physics_frames() == 0: - var timer: Timer = Timer.new() - var suppress_unsaved_marker: Callable - suppress_unsaved_marker = func(): - if Engine.get_frames_per_second() >= 10: - timer.stop() - get_editor_interface().save_all_scenes() - timer.queue_free() - timer.timeout.connect(suppress_unsaved_marker) - add_child(timer) - timer.start(0.1) - - -func _exit_tree() -> void: - remove_autoload_singleton("DialogueManager") - - remove_import_plugin(import_plugin) - import_plugin = null - - remove_translation_parser_plugin(translation_parser_plugin) - translation_parser_plugin = null - - if is_instance_valid(main_view): - main_view.queue_free() - - Engine.remove_meta("DialogueManagerPlugin") - Engine.remove_meta("DialogueCache") - - get_editor_interface().get_file_system_dock().files_moved.disconnect(_on_files_moved) - get_editor_interface().get_file_system_dock().file_removed.disconnect(_on_file_removed) - - remove_tool_menu_item("Create copy of dialogue example balloon...") - - -func _has_main_screen() -> bool: - return true - - -func _make_visible(next_visible: bool) -> void: - if is_instance_valid(main_view): - main_view.visible = next_visible - - -func _get_plugin_name() -> String: - return "Dialogue" - - -func _get_plugin_icon() -> Texture2D: - return load(get_plugin_path() + "/assets/icon.svg") - - -func _handles(object) -> bool: - var editor_settings: EditorSettings = get_editor_interface().get_editor_settings() - var external_editor: String = editor_settings.get_setting("text_editor/external/exec_path") - var use_external_editor: bool = editor_settings.get_setting("text_editor/external/use_external_editor") and external_editor != "" - if object is DialogueResource and use_external_editor and DialogueSettings.get_user_value("open_in_external_editor", false): - var project_path: String = ProjectSettings.globalize_path("res://") - var file_path: String = ProjectSettings.globalize_path(object.resource_path) - OS.create_process(external_editor, [project_path, file_path]) - return false - - return object is DialogueResource - - -func _edit(object) -> void: - if is_instance_valid(main_view) and is_instance_valid(object): - main_view.open_resource(object) - - -func _apply_changes() -> void: - if is_instance_valid(main_view): - main_view.apply_changes() - _update_localization() - - -func _build() -> bool: - # If this is the dotnet Godot then we need to check if the solution file exists - if ProjectSettings.has_setting("dotnet/project/solution_directory"): - var directory: String = ProjectSettings.get("dotnet/project/solution_directory") - var file_name: String = ProjectSettings.get("dotnet/project/assembly_name") - var has_dotnet_solution: bool = FileAccess.file_exists("res://%s/%s.sln" % [directory, file_name]) - DialogueSettings.set_user_value("has_dotnet_solution", has_dotnet_solution) - - # Ignore errors in other files if we are just running the test scene - if DialogueSettings.get_user_value("is_running_test_scene", true): return true - - if dialogue_cache != null: - var files_with_errors = dialogue_cache.get_files_with_errors() - if files_with_errors.size() > 0: - for dialogue_file in files_with_errors: - push_error("You have %d error(s) in %s" % [dialogue_file.errors.size(), dialogue_file.path]) - get_editor_interface().edit_resource(load(files_with_errors[0].path)) - main_view.show_build_error_dialog() - return false - - return true - - -## Get the current version -func get_version() -> String: - var config: ConfigFile = ConfigFile.new() - config.load(get_plugin_path() + "/plugin.cfg") - return config.get_value("plugin", "version") - - -## Get the current path of the plugin -func get_plugin_path() -> String: - return get_script().resource_path.get_base_dir() - - -## Update references to a moved file -func update_import_paths(from_path: String, to_path: String) -> void: - dialogue_cache.move_file_path(from_path, to_path) - - # Reopen the file if it's already open - if main_view.current_file_path == from_path: - if to_path == "": - main_view.close_file(from_path) - else: - main_view.current_file_path = "" - main_view.open_file(to_path) - - # Update any other files that import the moved file - var dependents = dialogue_cache.get_files_with_dependency(from_path) - for dependent in dependents: - dependent.dependencies.remove_at(dependent.dependencies.find(from_path)) - dependent.dependencies.append(to_path) - - # Update the live buffer - if main_view.current_file_path == dependent.path: - main_view.code_edit.text = main_view.code_edit.text.replace(from_path, to_path) - main_view.pristine_text = main_view.code_edit.text - - # Open the file and update the path - var file: FileAccess = FileAccess.open(dependent.path, FileAccess.READ) - var text = file.get_as_text().replace(from_path, to_path) - file.close() - - file = FileAccess.open(dependent.path, FileAccess.WRITE) - file.store_string(text) - file.close() - - -func _update_localization() -> void: - var dialogue_files = dialogue_cache.get_files() - - # Add any new files to POT generation - var files_for_pot: PackedStringArray = ProjectSettings.get_setting("internationalization/locale/translations_pot_files", []) - var files_for_pot_changed: bool = false - for path in dialogue_files: - if not files_for_pot.has(path): - files_for_pot.append(path) - files_for_pot_changed = true - - # Remove any POT references that don't exist any more - for i in range(files_for_pot.size() - 1, -1, -1): - var file_for_pot: String = files_for_pot[i] - if file_for_pot.get_extension() == "dialogue" and not dialogue_files.has(file_for_pot): - files_for_pot.remove_at(i) - files_for_pot_changed = true - - # Update project settings if POT changed - if files_for_pot_changed: - ProjectSettings.set_setting("internationalization/locale/translations_pot_files", files_for_pot) - ProjectSettings.save() - - -### Callbacks - - -func _copy_dialogue_balloon() -> void: - var scale: float = get_editor_interface().get_editor_scale() - var directory_dialog: FileDialog = FileDialog.new() - var label: Label = Label.new() - label.text = "Dialogue balloon files will be copied into chosen directory." - directory_dialog.get_vbox().add_child(label) - directory_dialog.file_mode = FileDialog.FILE_MODE_OPEN_DIR - directory_dialog.min_size = Vector2(600, 500) * scale - directory_dialog.dir_selected.connect(func(path): - var plugin_path: String = get_plugin_path() - - var is_dotnet: bool = DialogueSettings.has_dotnet_solution() - var balloon_path: String = path + ("/Balloon.tscn" if is_dotnet else "/balloon.tscn") - var balloon_script_path: String = path + ("/DialogueBalloon.cs" if is_dotnet else "/balloon.gd") - - # Copy the balloon scene file and change the script reference - var is_small_window: bool = ProjectSettings.get_setting("display/window/size/viewport_width") < 400 - var example_balloon_file_name: String = "small_example_balloon.tscn" if is_small_window else "example_balloon.tscn" - var example_balloon_script_file_name: String = "ExampleBalloon.cs" if is_dotnet else "example_balloon.gd" - var file: FileAccess = FileAccess.open(plugin_path + "/example_balloon/" + example_balloon_file_name, FileAccess.READ) - var file_contents: String = file.get_as_text().replace(plugin_path + "/example_balloon/example_balloon.gd", balloon_script_path) - file = FileAccess.open(balloon_path, FileAccess.WRITE) - file.store_string(file_contents) - file.close() - - # Copy the script file - file = FileAccess.open(plugin_path + "/example_balloon/" + example_balloon_script_file_name, FileAccess.READ) - file_contents = file.get_as_text() - if is_dotnet: - file_contents = file_contents.replace("class ExampleBalloon", "class DialogueBalloon") - file = FileAccess.open(balloon_script_path, FileAccess.WRITE) - file.store_string(file_contents) - file.close() - - get_editor_interface().get_resource_filesystem().scan() - get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", balloon_path) - - DialogueSettings.set_setting("balloon_path", balloon_path) - - directory_dialog.queue_free() - ) - get_editor_interface().get_base_control().add_child(directory_dialog) - directory_dialog.popup_centered() - - -### Signals - - -func _on_files_moved(old_file: String, new_file: String) -> void: - update_import_paths(old_file, new_file) - DialogueSettings.move_recent_file(old_file, new_file) - - -func _on_file_removed(file: String) -> void: - update_import_paths(file, "") - if is_instance_valid(main_view): - main_view.close_file(file) diff --git a/addons/dialogue_manager/settings.gd b/addons/dialogue_manager/settings.gd deleted file mode 100644 index b968a84..0000000 --- a/addons/dialogue_manager/settings.gd +++ /dev/null @@ -1,184 +0,0 @@ -@tool -extends Node - - -const DialogueConstants = preload("./constants.gd") - - -### Editor config - -const DEFAULT_SETTINGS = { - states = [], - missing_translations_are_errors = false, - export_characters_in_translation = true, - wrap_lines = false, - new_with_template = true, - include_all_responses = false, - ignore_missing_state_values = false, - custom_test_scene_path = preload("./test_scene.tscn").resource_path, - default_csv_locale = "en", - balloon_path = "", - create_lines_for_responses_with_characters = true, - include_character_in_translation_exports = false, - include_notes_in_translation_exports = false -} - - -static func prepare() -> void: - # Migrate previous keys - for key in [ - "states", - "missing_translations_are_errors", - "export_characters_in_translation", - "wrap_lines", - "new_with_template", - "include_all_responses", - "custom_test_scene_path" - ]: - if ProjectSettings.has_setting("dialogue_manager/%s" % key): - var value = ProjectSettings.get_setting("dialogue_manager/%s" % key) - ProjectSettings.set_setting("dialogue_manager/%s" % key, null) - set_setting(key, value) - - # Set up initial settings - for setting in DEFAULT_SETTINGS: - var setting_name: String = "dialogue_manager/general/%s" % setting - if not ProjectSettings.has_setting(setting_name): - set_setting(setting, DEFAULT_SETTINGS[setting]) - ProjectSettings.set_initial_value(setting_name, DEFAULT_SETTINGS[setting]) - if setting.ends_with("_path"): - ProjectSettings.add_property_info({ - "name": setting_name, - "type": TYPE_STRING, - "hint": PROPERTY_HINT_FILE, - }) - - ProjectSettings.save() - - -static func set_setting(key: String, value) -> void: - ProjectSettings.set_setting("dialogue_manager/general/%s" % key, value) - ProjectSettings.set_initial_value("dialogue_manager/general/%s" % key, DEFAULT_SETTINGS[key]) - ProjectSettings.save() - - -static func get_setting(key: String, default): - if ProjectSettings.has_setting("dialogue_manager/general/%s" % key): - return ProjectSettings.get_setting("dialogue_manager/general/%s" % key) - else: - return default - - -static func get_settings(only_keys: PackedStringArray = []) -> Dictionary: - var settings: Dictionary = {} - for key in DEFAULT_SETTINGS.keys(): - if only_keys.is_empty() or key in only_keys: - settings[key] = get_setting(key, DEFAULT_SETTINGS[key]) - return settings - - -### User config - - -static func get_user_config() -> Dictionary: - var user_config: Dictionary = { - check_for_updates = true, - just_refreshed = null, - recent_files = [], - reopen_files = [], - most_recent_reopen_file = "", - carets = {}, - run_title = "", - run_resource_path = "", - is_running_test_scene = false, - has_dotnet_solution = false, - open_in_external_editor = false - } - - if FileAccess.file_exists(DialogueConstants.USER_CONFIG_PATH): - var file: FileAccess = FileAccess.open(DialogueConstants.USER_CONFIG_PATH, FileAccess.READ) - user_config.merge(JSON.parse_string(file.get_as_text()), true) - - return user_config - - -static func save_user_config(user_config: Dictionary) -> void: - var file: FileAccess = FileAccess.open(DialogueConstants.USER_CONFIG_PATH, FileAccess.WRITE) - file.store_string(JSON.stringify(user_config)) - - -static func set_user_value(key: String, value) -> void: - var user_config: Dictionary = get_user_config() - user_config[key] = value - save_user_config(user_config) - - -static func get_user_value(key: String, default = null): - return get_user_config().get(key, default) - - -static func add_recent_file(path: String) -> void: - var recent_files: Array = get_user_value("recent_files", []) - if path in recent_files: - recent_files.erase(path) - recent_files.insert(0, path) - set_user_value("recent_files", recent_files) - - -static func move_recent_file(from_path: String, to_path: String) -> void: - var recent_files: Array = get_user_value("recent_files", []) - for i in range(0, recent_files.size()): - if recent_files[i] == from_path: - recent_files[i] = to_path - set_user_value("recent_files", recent_files) - - -static func remove_recent_file(path: String) -> void: - var recent_files: Array = get_user_value("recent_files", []) - if path in recent_files: - recent_files.erase(path) - set_user_value("recent_files", recent_files) - - -static func get_recent_files() -> Array: - return get_user_value("recent_files", []) - - -static func clear_recent_files() -> void: - set_user_value("recent_files", []) - set_user_value("carets", {}) - - -static func set_caret(path: String, cursor: Vector2) -> void: - var carets: Dictionary = get_user_value("carets", {}) - carets[path] = { - x = cursor.x, - y = cursor.y - } - set_user_value("carets", carets) - - -static func get_caret(path: String) -> Vector2: - var carets = get_user_value("carets", {}) - if carets.has(path): - var caret = carets.get(path) - return Vector2(caret.x, caret.y) - else: - return Vector2.ZERO - - -static func has_dotnet_solution() -> bool: - if get_user_value("has_dotnet_solution", false): return true - - if ProjectSettings.has_setting("dotnet/project/solution_directory"): - var directory: String = ProjectSettings.get("dotnet/project/solution_directory") - var file_name: String = ProjectSettings.get("dotnet/project/assembly_name") - var has_dotnet_solution: bool = FileAccess.file_exists("res://%s/%s.sln" % [directory, file_name]) - set_user_value("has_dotnet_solution", has_dotnet_solution) - return has_dotnet_solution - else: - var plugin_path: String = new().get_script().resource_path.get_base_dir() - if not ResourceLoader.exists(plugin_path + "/DialogueManager.cs"): return false - if load(plugin_path + "/DialogueManager.cs") == null: return false - - return true diff --git a/addons/dialogue_manager/test_scene.gd b/addons/dialogue_manager/test_scene.gd deleted file mode 100644 index 5fc073e..0000000 --- a/addons/dialogue_manager/test_scene.gd +++ /dev/null @@ -1,31 +0,0 @@ -class_name BaseDialogueTestScene extends Node2D - - -const DialogueSettings = preload("./settings.gd") - - -@onready var title: String = DialogueSettings.get_user_value("run_title") -@onready var resource: DialogueResource = load(DialogueSettings.get_user_value("run_resource_path")) - - -func _ready(): - var screen_index: int = DisplayServer.get_primary_screen() - DisplayServer.window_set_position(Vector2(DisplayServer.screen_get_position(screen_index)) + (DisplayServer.screen_get_size(screen_index) - DisplayServer.window_get_size()) * 0.5) - DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) - - # Normally you can just call DialogueManager directly but doing so before the plugin has been - # enabled in settings will throw a compiler error here so I'm using get_singleton instead. - var dialogue_manager = Engine.get_singleton("DialogueManager") - dialogue_manager.dialogue_ended.connect(_on_dialogue_ended) - dialogue_manager.show_dialogue_balloon(resource, title) - - -func _enter_tree() -> void: - DialogueSettings.set_user_value("is_running_test_scene", false) - - -### Signals - - -func _on_dialogue_ended(_resource: DialogueResource): - get_tree().quit() diff --git a/addons/dialogue_manager/test_scene.tscn b/addons/dialogue_manager/test_scene.tscn deleted file mode 100644 index f2bbd8d..0000000 --- a/addons/dialogue_manager/test_scene.tscn +++ /dev/null @@ -1,7 +0,0 @@ -[gd_scene load_steps=2 format=3] - -[ext_resource type="Script" path="res://addons/dialogue_manager/test_scene.gd" id="1_yupoh"] - - -[node name="TestScene" type="Node2D"] -script = ExtResource("1_yupoh") diff --git a/addons/dialogue_manager/utilities/builtins.gd b/addons/dialogue_manager/utilities/builtins.gd deleted file mode 100644 index f8442d4..0000000 --- a/addons/dialogue_manager/utilities/builtins.gd +++ /dev/null @@ -1,468 +0,0 @@ -extends Object - - -const DialogueConstants = preload("../constants.gd") - -const SUPPORTED_BUILTIN_TYPES = [ - TYPE_ARRAY, - TYPE_VECTOR2, - TYPE_VECTOR3, - TYPE_VECTOR4, - TYPE_DICTIONARY, - TYPE_QUATERNION, - TYPE_COLOR, - TYPE_SIGNAL -] - - -static var resolve_method_error: Error = OK - - -static func is_supported(thing) -> bool: - return typeof(thing) in SUPPORTED_BUILTIN_TYPES - - -static func resolve_property(builtin, property: String): - match typeof(builtin): - TYPE_ARRAY, TYPE_DICTIONARY, TYPE_QUATERNION: - return builtin[property] - - # Some types have constants that we need to manually resolve - - TYPE_VECTOR2: - return resolve_vector2_property(builtin, property) - TYPE_VECTOR3: - return resolve_vector3_property(builtin, property) - TYPE_VECTOR4: - return resolve_vector4_property(builtin, property) - TYPE_COLOR: - return resolve_color_property(builtin, property) - - -static func resolve_method(thing, method_name: String, args: Array): - resolve_method_error = OK - - # Resolve static methods manually - match typeof(thing): - TYPE_VECTOR2: - match method_name: - "from_angle": - return Vector2.from_angle(args[0]) - - TYPE_COLOR: - match method_name: - "from_hsv": - return Color.from_hsv(args[0], args[1], args[2]) if args.size() == 3 else Color.from_hsv(args[0], args[1], args[2], args[3]) - "from_ok_hsl": - return Color.from_ok_hsl(args[0], args[1], args[2]) if args.size() == 3 else Color.from_ok_hsl(args[0], args[1], args[2], args[3]) - "from_rgbe9995": - return Color.from_rgbe9995(args[0]) - "from_string": - return Color.from_string(args[0], args[1]) - - TYPE_QUATERNION: - match method_name: - "from_euler": - return Quaternion.from_euler(args[0]) - - # Anything else can be evaulatated automatically - var references: Array = ["thing"] - for i in range(0, args.size()): - references.append("arg%d" % i) - var expression = Expression.new() - if expression.parse("thing.%s(%s)" % [method_name, ",".join(references.slice(1))], references) != OK: - assert(false, expression.get_error_text()) - var result = expression.execute([thing] + args, null, false) - if expression.has_execute_failed(): - resolve_method_error = ERR_CANT_RESOLVE - return null - - return result - - -static func has_resolve_method_failed() -> bool: - return resolve_method_error != OK - - -static func resolve_color_property(color: Color, property: String): - match property: - "ALICE_BLUE": - return Color.ALICE_BLUE - "ANTIQUE_WHITE": - return Color.ANTIQUE_WHITE - "AQUA": - return Color.AQUA - "AQUAMARINE": - return Color.AQUAMARINE - "AZURE": - return Color.AZURE - "BEIGE": - return Color.BEIGE - "BISQUE": - return Color.BISQUE - "BLACK": - return Color.BLACK - "BLANCHED_ALMOND": - return Color.BLANCHED_ALMOND - "BLUE": - return Color.BLUE - "BLUE_VIOLET": - return Color.BLUE_VIOLET - "BROWN": - return Color.BROWN - "BURLYWOOD": - return Color.BURLYWOOD - "CADET_BLUE": - return Color.CADET_BLUE - "CHARTREUSE": - return Color.CHARTREUSE - "CHOCOLATE": - return Color.CHOCOLATE - "CORAL": - return Color.CORAL - "CORNFLOWER_BLUE": - return Color.CORNFLOWER_BLUE - "CORNSILK": - return Color.CORNSILK - "CRIMSON": - return Color.CRIMSON - "CYAN": - return Color.CYAN - "DARK_BLUE": - return Color.DARK_BLUE - "DARK_CYAN": - return Color.DARK_CYAN - "DARK_GOLDENROD": - return Color.DARK_GOLDENROD - "DARK_GRAY": - return Color.DARK_GRAY - "DARK_GREEN": - return Color.DARK_GREEN - "DARK_KHAKI": - return Color.DARK_KHAKI - "DARK_MAGENTA": - return Color.DARK_MAGENTA - "DARK_OLIVE_GREEN": - return Color.DARK_OLIVE_GREEN - "DARK_ORANGE": - return Color.DARK_ORANGE - "DARK_ORCHID": - return Color.DARK_ORCHID - "DARK_RED": - return Color.DARK_RED - "DARK_SALMON": - return Color.DARK_SALMON - "DARK_SEA_GREEN": - return Color.DARK_SEA_GREEN - "DARK_SLATE_BLUE": - return Color.DARK_SLATE_BLUE - "DARK_SLATE_GRAY": - return Color.DARK_SLATE_GRAY - "DARK_TURQUOISE": - return Color.DARK_TURQUOISE - "DARK_VIOLET": - return Color.DARK_VIOLET - "DEEP_PINK": - return Color.DEEP_PINK - "DEEP_SKY_BLUE": - return Color.DEEP_SKY_BLUE - "DIM_GRAY": - return Color.DIM_GRAY - "DODGER_BLUE": - return Color.DODGER_BLUE - "FIREBRICK": - return Color.FIREBRICK - "FLORAL_WHITE": - return Color.FLORAL_WHITE - "FOREST_GREEN": - return Color.FOREST_GREEN - "FUCHSIA": - return Color.FUCHSIA - "GAINSBORO": - return Color.GAINSBORO - "GHOST_WHITE": - return Color.GHOST_WHITE - "GOLD": - return Color.GOLD - "GOLDENROD": - return Color.GOLDENROD - "GRAY": - return Color.GRAY - "GREEN": - return Color.GREEN - "GREEN_YELLOW": - return Color.GREEN_YELLOW - "HONEYDEW": - return Color.HONEYDEW - "HOT_PINK": - return Color.HOT_PINK - "INDIAN_RED": - return Color.INDIAN_RED - "INDIGO": - return Color.INDIGO - "IVORY": - return Color.IVORY - "KHAKI": - return Color.KHAKI - "LAVENDER": - return Color.LAVENDER - "LAVENDER_BLUSH": - return Color.LAVENDER_BLUSH - "LAWN_GREEN": - return Color.LAWN_GREEN - "LEMON_CHIFFON": - return Color.LEMON_CHIFFON - "LIGHT_BLUE": - return Color.LIGHT_BLUE - "LIGHT_CORAL": - return Color.LIGHT_CORAL - "LIGHT_CYAN": - return Color.LIGHT_CYAN - "LIGHT_GOLDENROD": - return Color.LIGHT_GOLDENROD - "LIGHT_GRAY": - return Color.LIGHT_GRAY - "LIGHT_GREEN": - return Color.LIGHT_GREEN - "LIGHT_PINK": - return Color.LIGHT_PINK - "LIGHT_SALMON": - return Color.LIGHT_SALMON - "LIGHT_SEA_GREEN": - return Color.LIGHT_SEA_GREEN - "LIGHT_SKY_BLUE": - return Color.LIGHT_SKY_BLUE - "LIGHT_SLATE_GRAY": - return Color.LIGHT_SLATE_GRAY - "LIGHT_STEEL_BLUE": - return Color.LIGHT_STEEL_BLUE - "LIGHT_YELLOW": - return Color.LIGHT_YELLOW - "LIME": - return Color.LIME - "LIME_GREEN": - return Color.LIME_GREEN - "LINEN": - return Color.LINEN - "MAGENTA": - return Color.MAGENTA - "MAROON": - return Color.MAROON - "MEDIUM_AQUAMARINE": - return Color.MEDIUM_AQUAMARINE - "MEDIUM_BLUE": - return Color.MEDIUM_BLUE - "MEDIUM_ORCHID": - return Color.MEDIUM_ORCHID - "MEDIUM_PURPLE": - return Color.MEDIUM_PURPLE - "MEDIUM_SEA_GREEN": - return Color.MEDIUM_SEA_GREEN - "MEDIUM_SLATE_BLUE": - return Color.MEDIUM_SLATE_BLUE - "MEDIUM_SPRING_GREEN": - return Color.MEDIUM_SPRING_GREEN - "MEDIUM_TURQUOISE": - return Color.MEDIUM_TURQUOISE - "MEDIUM_VIOLET_RED": - return Color.MEDIUM_VIOLET_RED - "MIDNIGHT_BLUE": - return Color.MIDNIGHT_BLUE - "MINT_CREAM": - return Color.MINT_CREAM - "MISTY_ROSE": - return Color.MISTY_ROSE - "MOCCASIN": - return Color.MOCCASIN - "NAVAJO_WHITE": - return Color.NAVAJO_WHITE - "NAVY_BLUE": - return Color.NAVY_BLUE - "OLD_LACE": - return Color.OLD_LACE - "OLIVE": - return Color.OLIVE - "OLIVE_DRAB": - return Color.OLIVE_DRAB - "ORANGE": - return Color.ORANGE - "ORANGE_RED": - return Color.ORANGE_RED - "ORCHID": - return Color.ORCHID - "PALE_GOLDENROD": - return Color.PALE_GOLDENROD - "PALE_GREEN": - return Color.PALE_GREEN - "PALE_TURQUOISE": - return Color.PALE_TURQUOISE - "PALE_VIOLET_RED": - return Color.PALE_VIOLET_RED - "PAPAYA_WHIP": - return Color.PAPAYA_WHIP - "PEACH_PUFF": - return Color.PEACH_PUFF - "PERU": - return Color.PERU - "PINK": - return Color.PINK - "PLUM": - return Color.PLUM - "POWDER_BLUE": - return Color.POWDER_BLUE - "PURPLE": - return Color.PURPLE - "REBECCA_PURPLE": - return Color.REBECCA_PURPLE - "RED": - return Color.RED - "ROSY_BROWN": - return Color.ROSY_BROWN - "ROYAL_BLUE": - return Color.ROYAL_BLUE - "SADDLE_BROWN": - return Color.SADDLE_BROWN - "SALMON": - return Color.SALMON - "SANDY_BROWN": - return Color.SANDY_BROWN - "SEA_GREEN": - return Color.SEA_GREEN - "SEASHELL": - return Color.SEASHELL - "SIENNA": - return Color.SIENNA - "SILVER": - return Color.SILVER - "SKY_BLUE": - return Color.SKY_BLUE - "SLATE_BLUE": - return Color.SLATE_BLUE - "SLATE_GRAY": - return Color.SLATE_GRAY - "SNOW": - return Color.SNOW - "SPRING_GREEN": - return Color.SPRING_GREEN - "STEEL_BLUE": - return Color.STEEL_BLUE - "TAN": - return Color.TAN - "TEAL": - return Color.TEAL - "THISTLE": - return Color.THISTLE - "TOMATO": - return Color.TOMATO - "TRANSPARENT": - return Color.TRANSPARENT - "TURQUOISE": - return Color.TURQUOISE - "VIOLET": - return Color.VIOLET - "WEB_GRAY": - return Color.WEB_GRAY - "WEB_GREEN": - return Color.WEB_GREEN - "WEB_MAROON": - return Color.WEB_MAROON - "WEB_PURPLE": - return Color.WEB_PURPLE - "WHEAT": - return Color.WHEAT - "WHITE": - return Color.WHITE - "WHITE_SMOKE": - return Color.WHITE_SMOKE - "YELLOW": - return Color.YELLOW - "YELLOW_GREEN": - return Color.YELLOW_GREEN - - return color[property] - - -static func resolve_vector2_property(vector: Vector2, property: String): - match property: - "AXIS_X": - return Vector2.AXIS_X - "AXIS_Y": - return Vector2.AXIS_Y - "ZERO": - return Vector2.ZERO - "ONE": - return Vector2.ONE - "INF": - return Vector2.INF - "LEFT": - return Vector2.LEFT - "RIGHT": - return Vector2.RIGHT - "UP": - return Vector2.UP - "DOWN": - return Vector2.DOWN - - return vector[property] - - -static func resolve_vector3_property(vector: Vector3, property: String): - match property: - "AXIS_X": - return Vector3.AXIS_X - "AXIS_Y": - return Vector3.AXIS_Y - "AXIS_Z": - return Vector3.AXIS_Z - "ZERO": - return Vector3.ZERO - "ONE": - return Vector3.ONE - "INF": - return Vector3.INF - "LEFT": - return Vector3.LEFT - "RIGHT": - return Vector3.RIGHT - "UP": - return Vector3.UP - "DOWN": - return Vector3.DOWN - "FORWARD": - return Vector3.FORWARD - "BACK": - return Vector3.BACK - "MODEL_LEFT": - return Vector3(1, 0, 0) - "MODEL_RIGHT": - return Vector3(-1, 0, 0) - "MODEL_TOP": - return Vector3(0, 1, 0) - "MODEL_BOTTOM": - return Vector3(0, -1, 0) - "MODEL_FRONT": - return Vector3(0, 0, 1) - "MODEL_REAR": - return Vector3(0, 0, -1) - - return vector[property] - - -static func resolve_vector4_property(vector: Vector4, property: String): - match property: - "AXIS_X": - return Vector4.AXIS_X - "AXIS_Y": - return Vector4.AXIS_Y - "AXIS_Z": - return Vector4.AXIS_Z - "AXIS_W": - return Vector4.AXIS_W - "ZERO": - return Vector4.ZERO - "ONE": - return Vector4.ONE - "INF": - return Vector4.INF - - return vector[property] diff --git a/addons/dialogue_manager/views/main_view.gd b/addons/dialogue_manager/views/main_view.gd deleted file mode 100644 index 445d53d..0000000 --- a/addons/dialogue_manager/views/main_view.gd +++ /dev/null @@ -1,1100 +0,0 @@ -@tool -extends Control - - -const DialogueConstants = preload("../constants.gd") -const DialogueSettings = preload("../settings.gd") - -const OPEN_OPEN = 100 -const OPEN_CLEAR = 101 - -const TRANSLATIONS_GENERATE_LINE_IDS = 100 -const TRANSLATIONS_SAVE_CHARACTERS_TO_CSV = 201 -const TRANSLATIONS_SAVE_TO_CSV = 202 -const TRANSLATIONS_IMPORT_FROM_CSV = 203 - -const ITEM_SAVE = 100 -const ITEM_SAVE_AS = 101 -const ITEM_CLOSE = 102 -const ITEM_CLOSE_ALL = 103 -const ITEM_CLOSE_OTHERS = 104 -const ITEM_COPY_PATH = 200 -const ITEM_SHOW_IN_FILESYSTEM = 201 - -enum TranslationSource { - CharacterNames, - Lines -} - - -@onready var parse_timer := $ParseTimer - -# Dialogs -@onready var new_dialog: FileDialog = $NewDialog -@onready var save_dialog: FileDialog = $SaveDialog -@onready var open_dialog: FileDialog = $OpenDialog -@onready var export_dialog: FileDialog = $ExportDialog -@onready var import_dialog: FileDialog = $ImportDialog -@onready var errors_dialog: AcceptDialog = $ErrorsDialog -@onready var settings_dialog: AcceptDialog = $SettingsDialog -@onready var settings_view := $SettingsDialog/SettingsView -@onready var build_error_dialog: AcceptDialog = $BuildErrorDialog -@onready var close_confirmation_dialog: ConfirmationDialog = $CloseConfirmationDialog -@onready var updated_dialog: AcceptDialog = $UpdatedDialog -@onready var find_in_files_dialog: AcceptDialog = $FindInFilesDialog -@onready var find_in_files: Control = $FindInFilesDialog/FindInFiles - -# Toolbar -@onready var new_button: Button = %NewButton -@onready var open_button: MenuButton = %OpenButton -@onready var save_all_button: Button = %SaveAllButton -@onready var find_in_files_button: Button = %FindInFilesButton -@onready var test_button: Button = %TestButton -@onready var search_button: Button = %SearchButton -@onready var insert_button: MenuButton = %InsertButton -@onready var translations_button: MenuButton = %TranslationsButton -@onready var settings_button: Button = %SettingsButton -@onready var support_button: Button = %SupportButton -@onready var docs_button: Button = %DocsButton -@onready var version_label: Label = %VersionLabel -@onready var update_button: Button = %UpdateButton - -@onready var search_and_replace := %SearchAndReplace - -# Code editor -@onready var content: HSplitContainer = %Content -@onready var files_list := %FilesList -@onready var files_popup_menu: PopupMenu = %FilesPopupMenu -@onready var title_list := %TitleList -@onready var code_edit := %CodeEdit -@onready var errors_panel := %ErrorsPanel - -# The Dialogue Manager plugin -var editor_plugin: EditorPlugin - -# The currently open file -var current_file_path: String = "": - set(next_current_file_path): - current_file_path = next_current_file_path - files_list.current_file_path = current_file_path - if current_file_path == "": - save_all_button.disabled = true - test_button.disabled = true - search_button.disabled = true - insert_button.disabled = true - translations_button.disabled = true - content.dragger_visibility = SplitContainer.DRAGGER_HIDDEN - files_list.hide() - title_list.hide() - code_edit.hide() - errors_panel.hide() - else: - test_button.disabled = false - search_button.disabled = false - insert_button.disabled = false - translations_button.disabled = false - content.dragger_visibility = SplitContainer.DRAGGER_VISIBLE - files_list.show() - title_list.show() - code_edit.show() - - code_edit.text = open_buffers[current_file_path].text - code_edit.errors = [] - code_edit.clear_undo_history() - code_edit.set_cursor(DialogueSettings.get_caret(current_file_path)) - code_edit.grab_focus() - - _on_code_edit_text_changed() - - errors_panel.errors = [] - code_edit.errors = [] - get: - return current_file_path - -# A reference to the currently open files and their last saved text -var open_buffers: Dictionary = {} - -# Which thing are we exporting translations for? -var translation_source: TranslationSource = TranslationSource.Lines - - -func _ready() -> void: - apply_theme() - - # Start with nothing open - self.current_file_path = "" - - # Set up the update checker - version_label.text = "v%s" % editor_plugin.get_version() - update_button.editor_plugin = editor_plugin - update_button.on_before_refresh = func on_before_refresh(): - # Save everything - DialogueSettings.set_user_value("just_refreshed", { - current_file_path = current_file_path, - open_buffers = open_buffers - }) - return true - - # Did we just load from an addon version refresh? - var just_refreshed = DialogueSettings.get_user_value("just_refreshed", null) - if just_refreshed != null: - DialogueSettings.set_user_value("just_refreshed", null) - call_deferred("load_from_version_refresh", just_refreshed) - - # Hook up the search toolbar - search_and_replace.code_edit = code_edit - - # Connect menu buttons - insert_button.get_popup().id_pressed.connect(_on_insert_button_menu_id_pressed) - translations_button.get_popup().id_pressed.connect(_on_translations_button_menu_id_pressed) - - code_edit.main_view = self - code_edit.wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY if DialogueSettings.get_setting("wrap_lines", false) else TextEdit.LINE_WRAPPING_NONE - var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() - editor_settings.settings_changed.connect(_on_editor_settings_changed) - _on_editor_settings_changed() - - # Reopen any files that were open when Godot was closed - if editor_settings.get_setting("text_editor/behavior/files/restore_scripts_on_load"): - var reopen_files: Array = DialogueSettings.get_user_value("reopen_files", []) - for reopen_file in reopen_files: - open_file(reopen_file) - - self.current_file_path = DialogueSettings.get_user_value("most_recent_reopen_file", "") - - save_all_button.disabled = true - - close_confirmation_dialog.ok_button_text = DialogueConstants.translate(&"confirm_close.save") - close_confirmation_dialog.add_button(DialogueConstants.translate(&"confirm_close.discard"), true, "discard") - - settings_view.editor_plugin = editor_plugin - - errors_dialog.dialog_text = DialogueConstants.translate(&"errors_in_script") - - -func _exit_tree() -> void: - DialogueSettings.set_user_value("reopen_files", open_buffers.keys()) - DialogueSettings.set_user_value("most_recent_reopen_file", self.current_file_path) - - -func _unhandled_input(event: InputEvent) -> void: - if not visible: return - - if event is InputEventKey and event.is_pressed(): - match event.as_text(): - "Ctrl+Alt+S", "Command+Alt+S": - get_viewport().set_input_as_handled() - save_file(current_file_path) - "Ctrl+W", "Command+W": - get_viewport().set_input_as_handled() - close_file(current_file_path) - "Ctrl+F5", "Command+F5": - get_viewport().set_input_as_handled() - _on_test_button_pressed() - "Ctrl+Shift+F", "Command+Shift+F": - get_viewport().set_input_as_handled() - _on_find_in_files_button_pressed() - - -func apply_changes() -> void: - save_files() - - -# Load back to the previous buffer regardless of if it was actually saved -func load_from_version_refresh(just_refreshed: Dictionary) -> void: - if just_refreshed.has("current_file_content"): - # We just loaded from a version before multiple buffers - var file: FileAccess = FileAccess.open(just_refreshed.current_file_path, FileAccess.READ) - var file_text: String = file.get_as_text() - open_buffers[just_refreshed.current_file_path] = { - pristine_text = file_text, - text = just_refreshed.current_file_content - } - else: - open_buffers = just_refreshed.open_buffers - - if just_refreshed.current_file_path != "": - editor_plugin.get_editor_interface().edit_resource(load(just_refreshed.current_file_path)) - else: - editor_plugin.get_editor_interface().set_main_screen_editor("Dialogue") - - updated_dialog.dialog_text = DialogueConstants.translate(&"update.success").format({ version = update_button.get_version() }) - updated_dialog.popup_centered() - - -func new_file(path: String, content: String = "") -> void: - if open_buffers.has(path): - remove_file_from_open_buffers(path) - - var file: FileAccess = FileAccess.open(path, FileAccess.WRITE) - if content == "": - if DialogueSettings.get_setting("new_with_template", true): - file.store_string("\n".join([ - "~ this_is_a_node_title", - "", - "Nathan: [[Hi|Hello|Howdy]], this is some dialogue.", - "Nathan: Here are some choices.", - "- First one", - "\tNathan: You picked the first one.", - "- Second one", - "\tNathan: You picked the second one.", - "- Start again => this_is_a_node_title", - "- End the conversation => END", - "Nathan: For more information see the online documentation.", - "", - "=> END" - ])) - else: - file.store_string(content) - - editor_plugin.get_editor_interface().get_resource_filesystem().scan() - - -# Open a dialogue resource for editing -func open_resource(resource: DialogueResource) -> void: - open_file(resource.resource_path) - - -func open_file(path: String) -> void: - if not open_buffers.has(path): - var file: FileAccess = FileAccess.open(path, FileAccess.READ) - var text = file.get_as_text() - - open_buffers[path] = { - cursor = Vector2.ZERO, - text = text, - pristine_text = text - } - - DialogueSettings.add_recent_file(path) - build_open_menu() - - files_list.files = open_buffers.keys() - files_list.select_file(path) - - self.current_file_path = path - - -func show_file_in_filesystem(path: String) -> void: - var file_system_dock: FileSystemDock = Engine.get_meta("DialogueManagerPlugin") \ - .get_editor_interface() \ - .get_file_system_dock() - - file_system_dock.navigate_to_path(path) - - -# Save any open files -func save_files() -> void: - save_all_button.disabled = true - - var saved_files: PackedStringArray = [] - for path in open_buffers: - if open_buffers[path].text != open_buffers[path].pristine_text: - saved_files.append(path) - save_file(path, false) - - if saved_files.size() > 0: - Engine.get_meta("DialogueCache").reimport_files(saved_files) - - -# Save a file -func save_file(path: String, rescan_file_system: bool = true) -> void: - var buffer = open_buffers[path] - - files_list.mark_file_as_unsaved(path, false) - save_all_button.disabled = files_list.unsaved_files.size() == 0 - - # Don't bother saving if there is nothing to save - if buffer.text == buffer.pristine_text: - return - - buffer.pristine_text = buffer.text - - # Save the current text - var file: FileAccess = FileAccess.open(path, FileAccess.WRITE) - file.store_string(buffer.text) - file.close() - - if rescan_file_system: - Engine.get_meta("DialogueManagerPlugin") \ - .get_editor_interface() \ - .get_resource_filesystem()\ - .scan() - - -func close_file(file: String) -> void: - if not file in open_buffers.keys(): return - - var buffer = open_buffers[file] - - if buffer.text == buffer.pristine_text: - remove_file_from_open_buffers(file) - else: - close_confirmation_dialog.dialog_text = DialogueConstants.translate(&"confirm_close").format({ path = file.get_file() }) - close_confirmation_dialog.popup_centered() - - -func remove_file_from_open_buffers(file: String) -> void: - if not file in open_buffers.keys(): return - - var current_index = open_buffers.keys().find(file) - - open_buffers.erase(file) - if open_buffers.size() == 0: - self.current_file_path = "" - else: - current_index = clamp(current_index, 0, open_buffers.size() - 1) - self.current_file_path = open_buffers.keys()[current_index] - files_list.files = open_buffers.keys() - - -# Apply theme colors and icons to the UI -func apply_theme() -> void: - if is_instance_valid(editor_plugin) and is_instance_valid(code_edit): - var scale: float = editor_plugin.get_editor_interface().get_editor_scale() - var editor_settings = editor_plugin.get_editor_interface().get_editor_settings() - code_edit.theme_overrides = { - scale = scale, - - background_color = editor_settings.get_setting("text_editor/theme/highlighting/background_color"), - current_line_color = editor_settings.get_setting("text_editor/theme/highlighting/current_line_color"), - error_line_color = editor_settings.get_setting("text_editor/theme/highlighting/mark_color"), - - critical_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_markers/critical_color"), - notice_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_markers/notice_color"), - - titles_color = editor_settings.get_setting("text_editor/theme/highlighting/control_flow_keyword_color"), - text_color = editor_settings.get_setting("text_editor/theme/highlighting/text_color"), - conditions_color = editor_settings.get_setting("text_editor/theme/highlighting/keyword_color"), - mutations_color = editor_settings.get_setting("text_editor/theme/highlighting/function_color"), - members_color = editor_settings.get_setting("text_editor/theme/highlighting/member_variable_color"), - strings_color = editor_settings.get_setting("text_editor/theme/highlighting/string_color"), - numbers_color = editor_settings.get_setting("text_editor/theme/highlighting/number_color"), - symbols_color = editor_settings.get_setting("text_editor/theme/highlighting/symbol_color"), - comments_color = editor_settings.get_setting("text_editor/theme/highlighting/comment_color"), - jumps_color = Color(editor_settings.get_setting("text_editor/theme/highlighting/control_flow_keyword_color"), 0.7), - - font_size = editor_settings.get_setting("interface/editor/code_font_size") - } - - new_button.icon = get_theme_icon("New", "EditorIcons") - new_button.tooltip_text = DialogueConstants.translate(&"start_a_new_file") - - open_button.icon = get_theme_icon("Load", "EditorIcons") - open_button.tooltip_text = DialogueConstants.translate(&"open_a_file") - - save_all_button.icon = get_theme_icon("Save", "EditorIcons") - save_all_button.tooltip_text = DialogueConstants.translate(&"start_all_files") - - find_in_files_button.icon = get_theme_icon("ViewportZoom", "EditorIcons") - find_in_files_button.tooltip_text = DialogueConstants.translate(&"find_in_files") - - test_button.icon = get_theme_icon("PlayScene", "EditorIcons") - test_button.tooltip_text = DialogueConstants.translate(&"test_dialogue") - - search_button.icon = get_theme_icon("Search", "EditorIcons") - search_button.tooltip_text = DialogueConstants.translate(&"search_for_text") - - insert_button.icon = get_theme_icon("RichTextEffect", "EditorIcons") - insert_button.text = DialogueConstants.translate(&"insert") - - translations_button.icon = get_theme_icon("Translation", "EditorIcons") - translations_button.text = DialogueConstants.translate(&"translations") - - settings_button.icon = get_theme_icon("Tools", "EditorIcons") - settings_button.tooltip_text = DialogueConstants.translate(&"settings") - - support_button.icon = get_theme_icon("Heart", "EditorIcons") - support_button.text = DialogueConstants.translate(&"sponsor") - support_button.tooltip_text = DialogueConstants.translate(&"show_support") - - docs_button.icon = get_theme_icon("Help", "EditorIcons") - docs_button.text = DialogueConstants.translate(&"docs") - - update_button.apply_theme() - - # Set up the effect menu - var popup: PopupMenu = insert_button.get_popup() - popup.clear() - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.wave_bbcode"), 0) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.shake_bbcode"), 1) - popup.add_separator() - popup.add_icon_item(get_theme_icon("Time", "EditorIcons"), DialogueConstants.translate(&"insert.typing_pause"), 3) - popup.add_icon_item(get_theme_icon("ViewportSpeed", "EditorIcons"), DialogueConstants.translate(&"insert.typing_speed_change"), 4) - popup.add_icon_item(get_theme_icon("DebugNext", "EditorIcons"), DialogueConstants.translate(&"insert.auto_advance"), 5) - popup.add_separator(DialogueConstants.translate(&"insert.templates")) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.title"), 6) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.dialogue"), 7) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.response"), 8) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.random_lines"), 9) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.random_text"), 10) - popup.add_separator(DialogueConstants.translate(&"insert.actions")) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.jump"), 11) - popup.add_icon_item(get_theme_icon("RichTextEffect", "EditorIcons"), DialogueConstants.translate(&"insert.end_dialogue"), 12) - - # Set up the translations menu - popup = translations_button.get_popup() - popup.clear() - popup.add_icon_item(get_theme_icon("Translation", "EditorIcons"), DialogueConstants.translate(&"generate_line_ids"), TRANSLATIONS_GENERATE_LINE_IDS) - popup.add_separator() - popup.add_icon_item(get_theme_icon("FileList", "EditorIcons"), DialogueConstants.translate(&"save_characters_to_csv"), TRANSLATIONS_SAVE_CHARACTERS_TO_CSV) - popup.add_icon_item(get_theme_icon("FileList", "EditorIcons"), DialogueConstants.translate(&"save_to_csv"), TRANSLATIONS_SAVE_TO_CSV) - popup.add_icon_item(get_theme_icon("AssetLib", "EditorIcons"), DialogueConstants.translate(&"import_from_csv"), TRANSLATIONS_IMPORT_FROM_CSV) - - # Dialog sizes - new_dialog.min_size = Vector2(600, 500) * scale - save_dialog.min_size = Vector2(600, 500) * scale - open_dialog.min_size = Vector2(600, 500) * scale - export_dialog.min_size = Vector2(600, 500) * scale - import_dialog.min_size = Vector2(600, 500) * scale - settings_dialog.min_size = Vector2(1000, 600) * scale - settings_dialog.max_size = Vector2(1000, 600) * scale - find_in_files_dialog.min_size = Vector2(800, 600) * scale - - -### Helpers - - -# Refresh the open menu with the latest files -func build_open_menu() -> void: - var menu = open_button.get_popup() - menu.clear() - menu.add_icon_item(get_theme_icon("Load", "EditorIcons"), DialogueConstants.translate(&"open.open"), OPEN_OPEN) - menu.add_separator() - - var recent_files = DialogueSettings.get_recent_files() - if recent_files.size() == 0: - menu.add_item(DialogueConstants.translate(&"open.no_recent_files")) - menu.set_item_disabled(2, true) - else: - for path in recent_files: - if FileAccess.file_exists(path): - menu.add_icon_item(get_theme_icon("File", "EditorIcons"), path) - - menu.add_separator() - menu.add_item(DialogueConstants.translate(&"open.clear_recent_files"), OPEN_CLEAR) - if menu.id_pressed.is_connected(_on_open_menu_id_pressed): - menu.id_pressed.disconnect(_on_open_menu_id_pressed) - menu.id_pressed.connect(_on_open_menu_id_pressed) - - -# Get the last place a CSV, etc was exported -func get_last_export_path(extension: String) -> String: - var filename = current_file_path.get_file().replace(".dialogue", "." + extension) - return DialogueSettings.get_user_value("last_export_path", current_file_path.get_base_dir()) + "/" + filename - - -# Check the current text for errors -func parse() -> void: - # Skip if nothing to parse - if current_file_path == "": return - - var parser = DialogueManagerParser.new() - var errors: Array[Dictionary] = [] - if parser.parse(code_edit.text, current_file_path) != OK: - errors = parser.get_errors() - code_edit.errors = errors - errors_panel.errors = errors - parser.free() - - -func show_build_error_dialog() -> void: - build_error_dialog.dialog_text = DialogueConstants.translate(&"errors_with_build") - build_error_dialog.popup_centered() - - -# Generate translation line IDs for any line that doesn't already have one -func generate_translations_keys() -> void: - randomize() - seed(Time.get_unix_time_from_system()) - - var parser = DialogueManagerParser.new() - - var cursor: Vector2 = code_edit.get_cursor() - var lines: PackedStringArray = code_edit.text.split("\n") - - var key_regex = RegEx.new() - key_regex.compile("\\[ID:(?<key>.*?)\\]") - - # Make list of known keys - var known_keys = {} - for i in range(0, lines.size()): - var line = lines[i] - var found = key_regex.search(line) - if found: - var text = "" - var l = line.replace(found.strings[0], "").strip_edges().strip_edges() - if l.begins_with("- "): - text = parser.extract_response_prompt(l) - elif ":" in l: - text = l.split(":")[1] - else: - text = l - known_keys[found.strings[found.names.get("key")]] = text - - # Add in any that are missing - for i in lines.size(): - var line = lines[i] - var l = line.strip_edges() - - if parser.is_line_empty(l): continue - if parser.is_condition_line(l, true): continue - if parser.is_title_line(l): continue - if parser.is_mutation_line(l): continue - if parser.is_goto_line(l): continue - if parser.is_import_line(l): continue - - if "[ID:" in line: continue - - var key = "t" + str(randi() % 1000000).sha1_text().substr(0, 10) - while key in known_keys: - key = "t" + str(randi() % 1000000).sha1_text().substr(0, 10) - - var text = "" - if l.begins_with("- "): - text = parser.extract_response_prompt(l) - else: - text = l.substr(l.find(":") + 1) - - lines[i] = line.replace(text, text + " [ID:%s]" % key) - known_keys[key] = text - - code_edit.text = "\n".join(lines) - code_edit.set_cursor(cursor) - _on_code_edit_text_changed() - - parser.free() - - -# Add a translation file to the project settings -func add_path_to_project_translations(path: String) -> void: - var translations: PackedStringArray = ProjectSettings.get_setting("internationalization/locale/translations") - if not path in translations: - translations.append(path) - ProjectSettings.save() - - -# Export dialogue and responses to CSV -func export_translations_to_csv(path: String) -> void: - var default_locale: String = DialogueSettings.get_setting("default_csv_locale", "en") - - var file: FileAccess - - # If the file exists, open it first and work out which keys are already in it - var existing_csv: Dictionary = {} - var column_count: int = 2 - var default_locale_column: int = 1 - var character_column: int = -1 - var notes_column: int = -1 - if FileAccess.file_exists(path): - file = FileAccess.open(path, FileAccess.READ) - var is_first_line = true - var line: Array - while !file.eof_reached(): - line = file.get_csv_line() - if is_first_line: - is_first_line = false - column_count = line.size() - for i in range(1, line.size()): - if line[i] == default_locale: - default_locale_column = i - elif line[i] == "_character": - character_column = i - elif line[i] == "_notes": - notes_column = i - - # Make sure the line isn't empty before adding it - if line.size() > 0 and line[0].strip_edges() != "": - existing_csv[line[0]] = line - - # The character column wasn't found in the existing file but the setting is turned on - if character_column == -1 and DialogueSettings.get_setting("include_character_in_translation_exports", false): - character_column = column_count - column_count += 1 - existing_csv["keys"].append("_character") - - # The notes column wasn't found in the existing file but the setting is turned on - if notes_column == -1 and DialogueSettings.get_setting("include_notes_in_translation_exports", false): - notes_column = column_count - column_count += 1 - existing_csv["keys"].append("_notes") - - # Start a new file - file = FileAccess.open(path, FileAccess.WRITE) - - if not FileAccess.file_exists(path): - var headings: PackedStringArray = ["keys", default_locale] - if DialogueSettings.get_setting("include_character_in_translation_exports", false): - character_column = headings.size() - headings.append("_character") - if DialogueSettings.get_setting("include_notes_in_translation_exports", false): - notes_column = headings.size() - headings.append("_notes") - file.store_csv_line(headings) - column_count = headings.size() - - # Write our translations to file - var known_keys: PackedStringArray = [] - - var dialogue: Dictionary = DialogueManagerParser.parse_string(code_edit.text, current_file_path).lines - - # Make a list of stuff that needs to go into the file - var lines_to_save = [] - for key in dialogue.keys(): - var line: Dictionary = dialogue.get(key) - - if not line.type in [DialogueConstants.TYPE_DIALOGUE, DialogueConstants.TYPE_RESPONSE]: continue - if line.translation_key in known_keys: continue - - known_keys.append(line.translation_key) - - var line_to_save: PackedStringArray = [] - if existing_csv.has(line.translation_key): - line_to_save = existing_csv.get(line.translation_key) - line_to_save.resize(column_count) - existing_csv.erase(line.translation_key) - else: - line_to_save.resize(column_count) - line_to_save[0] = line.translation_key - - line_to_save[default_locale_column] = line.text - if character_column > -1: - line_to_save[character_column] = "(response)" if line.type == DialogueConstants.TYPE_RESPONSE else line.character - if notes_column > -1: - line_to_save[notes_column] = line.notes - - lines_to_save.append(line_to_save) - - # Store lines in the file, starting with anything that already exists that hasn't been touched - for line in existing_csv.values(): - file.store_csv_line(line) - for line in lines_to_save: - file.store_csv_line(line) - - file.close() - - editor_plugin.get_editor_interface().get_resource_filesystem().scan() - editor_plugin.get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", path) - - # Add it to the project l10n settings if it's not already there - var language_code: RegExMatch = RegEx.create_from_string("^[a-z]{2,3}").search(default_locale) - var translation_path: String = path.replace(".csv", ".%s.translation" % language_code.get_string()) - call_deferred("add_path_to_project_translations", translation_path) - - -func export_character_names_to_csv(path: String) -> void: - var file: FileAccess - - # If the file exists, open it first and work out which keys are already in it - var existing_csv = {} - var commas = [] - if FileAccess.file_exists(path): - file = FileAccess.open(path, FileAccess.READ) - var is_first_line = true - var line: Array - while !file.eof_reached(): - line = file.get_csv_line() - if is_first_line: - is_first_line = false - for i in range(2, line.size()): - commas.append("") - # Make sure the line isn't empty before adding it - if line.size() > 0 and line[0].strip_edges() != "": - existing_csv[line[0]] = line - - # Start a new file - file = FileAccess.open(path, FileAccess.WRITE) - - if not file.file_exists(path): - file.store_csv_line(["keys", DialogueSettings.get_setting("default_csv_locale", "en")]) - - # Write our translations to file - var known_keys: PackedStringArray = [] - - var character_names: PackedStringArray = DialogueManagerParser.parse_string(code_edit.text, current_file_path).character_names - - # Make a list of stuff that needs to go into the file - var lines_to_save = [] - for character_name in character_names: - if character_name in known_keys: continue - - known_keys.append(character_name) - - if existing_csv.has(character_name): - var existing_line = existing_csv.get(character_name) - existing_line[1] = character_name - lines_to_save.append(existing_line) - existing_csv.erase(character_name) - else: - lines_to_save.append(PackedStringArray([character_name, character_name] + commas)) - - # Store lines in the file, starting with anything that already exists that hasn't been touched - for line in existing_csv.values(): - file.store_csv_line(line) - for line in lines_to_save: - file.store_csv_line(line) - - file.close() - - editor_plugin.get_editor_interface().get_resource_filesystem().scan() - editor_plugin.get_editor_interface().get_file_system_dock().call_deferred("navigate_to_path", path) - - # Add it to the project l10n settings if it's not already there - var translation_path: String = path.replace(".csv", ".en.translation") - call_deferred("add_path_to_project_translations", translation_path) - - -# Import changes back from an exported CSV by matching translation keys -func import_translations_from_csv(path: String) -> void: - var cursor: Vector2 = code_edit.get_cursor() - - if not FileAccess.file_exists(path): return - - # Open the CSV file and build a dictionary of the known keys - var keys: Dictionary = {} - var file: FileAccess = FileAccess.open(path, FileAccess.READ) - var csv_line: Array - while !file.eof_reached(): - csv_line = file.get_csv_line() - if csv_line.size() > 1: - keys[csv_line[0]] = csv_line[1] - - var parser: DialogueManagerParser = DialogueManagerParser.new() - - # Now look over each line in the dialogue and replace the content for matched keys - var lines: PackedStringArray = code_edit.text.split("\n") - var start_index: int = 0 - var end_index: int = 0 - for i in range(0, lines.size()): - var line: String = lines[i] - var translation_key: String = parser.extract_translation(line) - if keys.has(translation_key): - if parser.is_dialogue_line(line): - start_index = 0 - # See if we need to skip over a character name - line = line.replace("\\:", "!ESCAPED_COLON!") - if ": " in line: - start_index = line.find(": ") + 2 - lines[i] = (line.substr(0, start_index) + keys.get(translation_key) + " [ID:" + translation_key + "]").replace("!ESCAPED_COLON!", ":") - - elif parser.is_response_line(line): - start_index = line.find("- ") + 2 - # See if we need to skip over a character name - line = line.replace("\\:", "!ESCAPED_COLON!") - if ": " in line: - start_index = line.find(": ") + 2 - end_index = line.length() - if " =>" in line: - end_index = line.find(" =>") - if " [if " in line: - end_index = line.find(" [if ") - lines[i] = (line.substr(0, start_index) + keys.get(translation_key) + " [ID:" + translation_key + "]" + line.substr(end_index)).replace("!ESCAPED_COLON!", ":") - - code_edit.text = "\n".join(lines) - code_edit.set_cursor(cursor) - - parser.free() - - -func show_search_form(is_enabled: bool) -> void: - if code_edit.last_selected_text: - search_and_replace.input.text = code_edit.last_selected_text - - search_and_replace.visible = is_enabled - search_button.set_pressed_no_signal(is_enabled) - search_and_replace.focus_line_edit() - - -### Signals - - -func _on_editor_settings_changed() -> void: - var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() - code_edit.minimap_draw = editor_settings.get_setting("text_editor/appearance/minimap/show_minimap") - code_edit.minimap_width = editor_settings.get_setting("text_editor/appearance/minimap/minimap_width") - code_edit.scroll_smooth = editor_settings.get_setting("text_editor/behavior/navigation/smooth_scrolling") - - -func _on_open_menu_id_pressed(id: int) -> void: - match id: - OPEN_OPEN: - open_dialog.popup_centered() - OPEN_CLEAR: - DialogueSettings.clear_recent_files() - build_open_menu() - _: - var menu = open_button.get_popup() - var item = menu.get_item_text(menu.get_item_index(id)) - open_file(item) - - -func _on_files_list_file_selected(file_path: String) -> void: - self.current_file_path = file_path - - -func _on_insert_button_menu_id_pressed(id: int) -> void: - match id: - 0: - code_edit.insert_bbcode("[wave amp=25 freq=5]", "[/wave]") - 1: - code_edit.insert_bbcode("[shake rate=20 level=10]", "[/shake]") - 3: - code_edit.insert_bbcode("[wait=1]") - 4: - code_edit.insert_bbcode("[speed=0.2]") - 5: - code_edit.insert_bbcode("[next=auto]") - 6: - code_edit.insert_text("~ title") - 7: - code_edit.insert_text("Nathan: This is Some Dialogue") - 8: - code_edit.insert_text("Nathan: Choose a Response...\n- Option 1\n\tNathan: You chose option 1\n- Option 2\n\tNathan: You chose option 2") - 9: - code_edit.insert_text("% Nathan: This is random line 1.\n% Nathan: This is random line 2.\n%1 Nathan: This is weighted random line 3.") - 10: - code_edit.insert_text("Nathan: [[Hi|Hello|Howdy]]") - 11: - code_edit.insert_text("=> title") - 12: - code_edit.insert_text("=> END") - - -func _on_translations_button_menu_id_pressed(id: int) -> void: - match id: - TRANSLATIONS_GENERATE_LINE_IDS: - generate_translations_keys() - - TRANSLATIONS_SAVE_CHARACTERS_TO_CSV: - translation_source = TranslationSource.CharacterNames - export_dialog.filters = PackedStringArray(["*.csv ; Translation CSV"]) - export_dialog.current_path = get_last_export_path("csv") - export_dialog.popup_centered() - - TRANSLATIONS_SAVE_TO_CSV: - translation_source = TranslationSource.Lines - export_dialog.filters = PackedStringArray(["*.csv ; Translation CSV"]) - export_dialog.current_path = get_last_export_path("csv") - export_dialog.popup_centered() - - TRANSLATIONS_IMPORT_FROM_CSV: - import_dialog.current_path = get_last_export_path("csv") - import_dialog.popup_centered() - - -func _on_export_dialog_file_selected(path: String) -> void: - DialogueSettings.set_user_value("last_export_path", path.get_base_dir()) - match path.get_extension(): - "csv": - match translation_source: - TranslationSource.CharacterNames: - export_character_names_to_csv(path) - TranslationSource.Lines: - export_translations_to_csv(path) - - -func _on_import_dialog_file_selected(path: String) -> void: - DialogueSettings.set_user_value("last_export_path", path.get_base_dir()) - import_translations_from_csv(path) - - -func _on_main_view_theme_changed(): - apply_theme() - - -func _on_main_view_visibility_changed() -> void: - if visible and is_instance_valid(code_edit): - code_edit.grab_focus() - - -func _on_new_button_pressed() -> void: - new_dialog.current_file = "" - new_dialog.popup_centered() - - -func _on_new_dialog_file_selected(path: String) -> void: - new_file(path) - open_file(path) - - -func _on_save_dialog_file_selected(path: String) -> void: - new_file(path, code_edit.text) - open_file(path) - - -func _on_open_button_about_to_popup() -> void: - build_open_menu() - - -func _on_open_dialog_file_selected(path: String) -> void: - open_file(path) - - -func _on_save_all_button_pressed() -> void: - save_files() - - -func _on_find_in_files_button_pressed() -> void: - find_in_files_dialog.popup_centered() - find_in_files.prepare() - - -func _on_code_edit_text_changed() -> void: - title_list.titles = code_edit.get_titles() - - var buffer = open_buffers[current_file_path] - buffer.text = code_edit.text - - files_list.mark_file_as_unsaved(current_file_path, buffer.text != buffer.pristine_text) - save_all_button.disabled = open_buffers.values().filter(func(d): return d.text != d.pristine_text).size() == 0 - - parse_timer.start(1) - - -func _on_code_edit_active_title_change(title: String) -> void: - title_list.select_title(title) - DialogueSettings.set_user_value("run_title", title) - - -func _on_code_edit_caret_changed() -> void: - DialogueSettings.set_caret(current_file_path, code_edit.get_cursor()) - - -func _on_code_edit_error_clicked(line_number: int) -> void: - errors_panel.show_error_for_line_number(line_number) - - -func _on_title_list_title_selected(title: String) -> void: - code_edit.go_to_title(title) - code_edit.grab_focus() - - -func _on_parse_timer_timeout() -> void: - parse_timer.stop() - parse() - - -func _on_errors_panel_error_pressed(line_number: int, column_number: int) -> void: - code_edit.set_caret_line(line_number) - code_edit.set_caret_column(column_number) - code_edit.grab_focus() - - -func _on_search_button_toggled(button_pressed: bool) -> void: - show_search_form(button_pressed) - - -func _on_search_and_replace_open_requested() -> void: - show_search_form(true) - - -func _on_search_and_replace_close_requested() -> void: - search_button.set_pressed_no_signal(false) - search_and_replace.visible = false - code_edit.grab_focus() - - -func _on_settings_button_pressed() -> void: - settings_view.prepare() - settings_dialog.popup_centered() - - -func _on_settings_view_script_button_pressed(path: String) -> void: - settings_dialog.hide() - editor_plugin.get_editor_interface().edit_resource(load(path)) - - -func _on_test_button_pressed() -> void: - save_file(current_file_path) - - if errors_panel.errors.size() > 0: - errors_dialog.popup_centered() - return - - DialogueSettings.set_user_value("is_running_test_scene", true) - DialogueSettings.set_user_value("run_resource_path", current_file_path) - var test_scene_path: String = DialogueSettings.get_setting("custom_test_scene_path", "res://addons/dialogue_manager/test_scene.tscn") - editor_plugin.get_editor_interface().play_custom_scene(test_scene_path) - - -func _on_settings_dialog_confirmed() -> void: - settings_view.apply_settings_changes() - parse() - code_edit.wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY if DialogueSettings.get_setting("wrap_lines", false) else TextEdit.LINE_WRAPPING_NONE - code_edit.grab_focus() - - -func _on_support_button_pressed() -> void: - OS.shell_open("https://patreon.com/nathanhoad") - - -func _on_docs_button_pressed() -> void: - OS.shell_open("https://github.com/nathanhoad/godot_dialogue_manager") - - -func _on_files_list_file_popup_menu_requested(at_position: Vector2) -> void: - files_popup_menu.position = Vector2(get_viewport().position) + files_list.global_position + at_position - files_popup_menu.popup() - - -func _on_files_list_file_middle_clicked(path: String): - close_file(path) - - -func _on_files_popup_menu_about_to_popup() -> void: - files_popup_menu.clear() - - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save"), ITEM_SAVE, KEY_MASK_CTRL | KEY_MASK_ALT | KEY_S) - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save_as"), ITEM_SAVE_AS) - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close"), ITEM_CLOSE, KEY_MASK_CTRL | KEY_W) - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_all"), ITEM_CLOSE_ALL) - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_other_files"), ITEM_CLOSE_OTHERS) - files_popup_menu.add_separator() - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.copy_file_path"), ITEM_COPY_PATH) - files_popup_menu.add_item(DialogueConstants.translate(&"buffer.show_in_filesystem"), ITEM_SHOW_IN_FILESYSTEM) - - -func _on_files_popup_menu_id_pressed(id: int) -> void: - match id: - ITEM_SAVE: - save_file(current_file_path) - ITEM_SAVE_AS: - save_dialog.popup_centered() - ITEM_CLOSE: - close_file(current_file_path) - ITEM_CLOSE_ALL: - for path in open_buffers.keys(): - close_file(path) - ITEM_CLOSE_OTHERS: - for path in open_buffers.keys(): - if path != current_file_path: - close_file(path) - - ITEM_COPY_PATH: - DisplayServer.clipboard_set(current_file_path) - ITEM_SHOW_IN_FILESYSTEM: - show_file_in_filesystem(current_file_path) - - -func _on_code_edit_external_file_requested(path: String, title: String) -> void: - open_file(path) - if title != "": - code_edit.go_to_title(title) - else: - code_edit.set_caret_line(0) - - -func _on_close_confirmation_dialog_confirmed() -> void: - save_file(current_file_path) - remove_file_from_open_buffers(current_file_path) - - -func _on_close_confirmation_dialog_custom_action(action: StringName) -> void: - if action == "discard": - remove_file_from_open_buffers(current_file_path) - close_confirmation_dialog.hide() - - -func _on_find_in_files_result_selected(path: String, cursor: Vector2, length: int) -> void: - open_file(path) - code_edit.select(cursor.y, cursor.x, cursor.y, cursor.x + length) diff --git a/addons/dialogue_manager/views/main_view.tscn b/addons/dialogue_manager/views/main_view.tscn deleted file mode 100644 index d57bdf9..0000000 --- a/addons/dialogue_manager/views/main_view.tscn +++ /dev/null @@ -1,334 +0,0 @@ -[gd_scene load_steps=14 format=3 uid="uid://cbuf1q3xsse3q"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/views/main_view.gd" id="1_h6qfq"] -[ext_resource type="PackedScene" uid="uid://civ6shmka5e8u" path="res://addons/dialogue_manager/components/code_edit.tscn" id="2_f73fm"] -[ext_resource type="PackedScene" uid="uid://dnufpcdrreva3" path="res://addons/dialogue_manager/components/files_list.tscn" id="2_npj2k"] -[ext_resource type="PackedScene" uid="uid://ctns6ouwwd68i" path="res://addons/dialogue_manager/components/title_list.tscn" id="2_onb4i"] -[ext_resource type="PackedScene" uid="uid://co8yl23idiwbi" path="res://addons/dialogue_manager/components/update_button.tscn" id="2_ph3vs"] -[ext_resource type="PackedScene" uid="uid://gr8nakpbrhby" path="res://addons/dialogue_manager/components/search_and_replace.tscn" id="6_ylh0t"] -[ext_resource type="PackedScene" uid="uid://cs8pwrxr5vxix" path="res://addons/dialogue_manager/components/errors_panel.tscn" id="7_5cvl4"] -[ext_resource type="Script" path="res://addons/dialogue_manager/components/code_edit_syntax_highlighter.gd" id="7_necsa"] -[ext_resource type="PackedScene" uid="uid://cpg4lg1r3ff6m" path="res://addons/dialogue_manager/views/settings_view.tscn" id="9_8bf36"] -[ext_resource type="PackedScene" uid="uid://0n7hwviyyly4" path="res://addons/dialogue_manager/components/find_in_files.tscn" id="10_yold3"] - -[sub_resource type="Image" id="Image_xvtti"] -data = { -"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), -"format": "RGBA8", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_fguub"] -image = SubResource("Image_xvtti") - -[sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_dvnxt"] -script = ExtResource("7_necsa") - -[node name="MainView" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -script = ExtResource("1_h6qfq") - -[node name="ParseTimer" type="Timer" parent="."] - -[node name="Margin" type="MarginContainer" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_vertical = 3 -theme_override_constants/margin_left = 5 -theme_override_constants/margin_right = 5 -theme_override_constants/margin_bottom = 5 -metadata/_edit_layout_mode = 1 - -[node name="Content" type="HSplitContainer" parent="Margin"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_vertical = 3 -dragger_visibility = 1 - -[node name="SidePanel" type="VBoxContainer" parent="Margin/Content"] -custom_minimum_size = Vector2(150, 0) -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="Toolbar" type="HBoxContainer" parent="Margin/Content/SidePanel"] -layout_mode = 2 - -[node name="NewButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -tooltip_text = "Start a new file" -flat = true - -[node name="OpenButton" type="MenuButton" parent="Margin/Content/SidePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -tooltip_text = "Open a file" - -[node name="SaveAllButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -disabled = true -flat = true - -[node name="FindInFilesButton" type="Button" parent="Margin/Content/SidePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -flat = true - -[node name="Bookmarks" type="VSplitContainer" parent="Margin/Content/SidePanel"] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="FilesList" parent="Margin/Content/SidePanel/Bookmarks" instance=ExtResource("2_npj2k")] -unique_name_in_owner = true -visible = false -layout_mode = 2 -size_flags_vertical = 3 - -[node name="FilesPopupMenu" type="PopupMenu" parent="Margin/Content/SidePanel/Bookmarks/FilesList"] -unique_name_in_owner = true - -[node name="TitleList" parent="Margin/Content/SidePanel/Bookmarks" instance=ExtResource("2_onb4i")] -unique_name_in_owner = true -visible = false -layout_mode = 2 - -[node name="CodePanel" type="VBoxContainer" parent="Margin/Content"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_stretch_ratio = 4.0 - -[node name="Toolbar" type="HBoxContainer" parent="Margin/Content/CodePanel"] -layout_mode = 2 - -[node name="InsertButton" type="MenuButton" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -disabled = true -text = "Insert" - -[node name="TranslationsButton" type="MenuButton" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -disabled = true -text = "Translations" -item_count = 6 -popup/item_0/text = "Generate line IDs" -popup/item_0/icon = SubResource("ImageTexture_fguub") -popup/item_0/id = 0 -popup/item_1/text = "" -popup/item_1/id = -1 -popup/item_1/separator = true -popup/item_2/text = "Save to CSV..." -popup/item_2/icon = SubResource("ImageTexture_fguub") -popup/item_2/id = 2 -popup/item_3/text = "Import changes from CSV..." -popup/item_3/icon = SubResource("ImageTexture_fguub") -popup/item_3/id = 3 -popup/item_4/text = "" -popup/item_4/id = -1 -popup/item_4/separator = true -popup/item_5/text = "Save to PO..." -popup/item_5/icon = SubResource("ImageTexture_fguub") -popup/item_5/id = 5 - -[node name="Separator" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] -layout_mode = 2 - -[node name="SearchButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -tooltip_text = "Search for text" -disabled = true -toggle_mode = true -flat = true - -[node name="TestButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -tooltip_text = "Test dialogue" -disabled = true -flat = true - -[node name="Separator3" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] -layout_mode = 2 - -[node name="SettingsButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -tooltip_text = "Settings" -flat = true - -[node name="Spacer2" type="Control" parent="Margin/Content/CodePanel/Toolbar"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="SupportButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -flat = true - -[node name="Separator4" type="VSeparator" parent="Margin/Content/CodePanel/Toolbar"] -layout_mode = 2 - -[node name="DocsButton" type="Button" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -layout_mode = 2 -text = "Docs" -flat = true - -[node name="VersionLabel" type="Label" parent="Margin/Content/CodePanel/Toolbar"] -unique_name_in_owner = true -modulate = Color(1, 1, 1, 0.490196) -layout_mode = 2 -text = "v2.19.0" -vertical_alignment = 1 - -[node name="UpdateButton" parent="Margin/Content/CodePanel/Toolbar" instance=ExtResource("2_ph3vs")] -unique_name_in_owner = true -layout_mode = 2 - -[node name="SearchAndReplace" parent="Margin/Content/CodePanel" instance=ExtResource("6_ylh0t")] -unique_name_in_owner = true -layout_mode = 2 - -[node name="CodeEdit" parent="Margin/Content/CodePanel" instance=ExtResource("2_f73fm")] -unique_name_in_owner = true -visible = false -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -theme_override_colors/bookmark_color = Color(1, 0.333333, 0.333333, 1) -text = "" -syntax_highlighter = SubResource("SyntaxHighlighter_dvnxt") - -[node name="ErrorsPanel" parent="Margin/Content/CodePanel" instance=ExtResource("7_5cvl4")] -unique_name_in_owner = true -layout_mode = 2 - -[node name="NewDialog" type="FileDialog" parent="."] -size = Vector2i(600, 500) -min_size = Vector2i(600, 500) -dialog_hide_on_ok = true -filters = PackedStringArray("*.dialogue ; Dialogue") - -[node name="SaveDialog" type="FileDialog" parent="."] -size = Vector2i(600, 500) -min_size = Vector2i(600, 500) -dialog_hide_on_ok = true -filters = PackedStringArray("*.dialogue ; Dialogue") - -[node name="OpenDialog" type="FileDialog" parent="."] -title = "Open a File" -size = Vector2i(600, 500) -min_size = Vector2i(600, 500) -ok_button_text = "Open" -dialog_hide_on_ok = true -file_mode = 0 -filters = PackedStringArray("*.dialogue ; Dialogue") - -[node name="ExportDialog" type="FileDialog" parent="."] -size = Vector2i(600, 500) -min_size = Vector2i(600, 500) - -[node name="ImportDialog" type="FileDialog" parent="."] -title = "Open a File" -size = Vector2i(600, 500) -min_size = Vector2i(600, 500) -ok_button_text = "Open" -file_mode = 0 -filters = PackedStringArray("*.csv ; Translation CSV") - -[node name="ErrorsDialog" type="AcceptDialog" parent="."] -title = "Error" -dialog_text = "You have errors in your script. Fix them and then try again." - -[node name="SettingsDialog" type="AcceptDialog" parent="."] -title = "Settings" -size = Vector2i(834, 600) -unresizable = true -min_size = Vector2i(600, 600) -ok_button_text = "Done" - -[node name="SettingsView" parent="SettingsDialog" instance=ExtResource("9_8bf36")] -offset_left = 8.0 -offset_top = 8.0 -offset_right = -8.0 -offset_bottom = -49.0 - -[node name="BuildErrorDialog" type="AcceptDialog" parent="."] -title = "Errors" -dialog_text = "You need to fix dialogue errors before you can run your game." - -[node name="CloseConfirmationDialog" type="ConfirmationDialog" parent="."] -title = "Unsaved changes" -ok_button_text = "Save changes" - -[node name="UpdatedDialog" type="AcceptDialog" parent="."] -title = "Updated" -size = Vector2i(191, 100) -dialog_text = "You're now up to date!" - -[node name="FindInFilesDialog" type="AcceptDialog" parent="."] -title = "Find in files" -size = Vector2i(416, 457) -ok_button_text = "Done" - -[node name="FindInFiles" parent="FindInFilesDialog" node_paths=PackedStringArray("main_view", "code_edit") instance=ExtResource("10_yold3")] -custom_minimum_size = Vector2(400, 400) -offset_left = 8.0 -offset_top = 8.0 -offset_right = -8.0 -offset_bottom = -49.0 -main_view = NodePath("../..") -code_edit = NodePath("../../Margin/Content/CodePanel/CodeEdit") - -[connection signal="theme_changed" from="." to="." method="_on_main_view_theme_changed"] -[connection signal="visibility_changed" from="." to="." method="_on_main_view_visibility_changed"] -[connection signal="timeout" from="ParseTimer" to="." method="_on_parse_timer_timeout"] -[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/NewButton" to="." method="_on_new_button_pressed"] -[connection signal="about_to_popup" from="Margin/Content/SidePanel/Toolbar/OpenButton" to="." method="_on_open_button_about_to_popup"] -[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/SaveAllButton" to="." method="_on_save_all_button_pressed"] -[connection signal="pressed" from="Margin/Content/SidePanel/Toolbar/FindInFilesButton" to="." method="_on_find_in_files_button_pressed"] -[connection signal="file_middle_clicked" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_middle_clicked"] -[connection signal="file_popup_menu_requested" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_popup_menu_requested"] -[connection signal="file_selected" from="Margin/Content/SidePanel/Bookmarks/FilesList" to="." method="_on_files_list_file_selected"] -[connection signal="about_to_popup" from="Margin/Content/SidePanel/Bookmarks/FilesList/FilesPopupMenu" to="." method="_on_files_popup_menu_about_to_popup"] -[connection signal="id_pressed" from="Margin/Content/SidePanel/Bookmarks/FilesList/FilesPopupMenu" to="." method="_on_files_popup_menu_id_pressed"] -[connection signal="title_selected" from="Margin/Content/SidePanel/Bookmarks/TitleList" to="." method="_on_title_list_title_selected"] -[connection signal="toggled" from="Margin/Content/CodePanel/Toolbar/SearchButton" to="." method="_on_search_button_toggled"] -[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/TestButton" to="." method="_on_test_button_pressed"] -[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/SettingsButton" to="." method="_on_settings_button_pressed"] -[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/SupportButton" to="." method="_on_support_button_pressed"] -[connection signal="pressed" from="Margin/Content/CodePanel/Toolbar/DocsButton" to="." method="_on_docs_button_pressed"] -[connection signal="close_requested" from="Margin/Content/CodePanel/SearchAndReplace" to="." method="_on_search_and_replace_close_requested"] -[connection signal="open_requested" from="Margin/Content/CodePanel/SearchAndReplace" to="." method="_on_search_and_replace_open_requested"] -[connection signal="active_title_change" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_active_title_change"] -[connection signal="caret_changed" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_caret_changed"] -[connection signal="error_clicked" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_error_clicked"] -[connection signal="external_file_requested" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_external_file_requested"] -[connection signal="text_changed" from="Margin/Content/CodePanel/CodeEdit" to="." method="_on_code_edit_text_changed"] -[connection signal="error_pressed" from="Margin/Content/CodePanel/ErrorsPanel" to="." method="_on_errors_panel_error_pressed"] -[connection signal="file_selected" from="NewDialog" to="." method="_on_new_dialog_file_selected"] -[connection signal="file_selected" from="SaveDialog" to="." method="_on_save_dialog_file_selected"] -[connection signal="file_selected" from="OpenDialog" to="." method="_on_open_dialog_file_selected"] -[connection signal="file_selected" from="ExportDialog" to="." method="_on_export_dialog_file_selected"] -[connection signal="file_selected" from="ImportDialog" to="." method="_on_import_dialog_file_selected"] -[connection signal="confirmed" from="SettingsDialog" to="." method="_on_settings_dialog_confirmed"] -[connection signal="script_button_pressed" from="SettingsDialog/SettingsView" to="." method="_on_settings_view_script_button_pressed"] -[connection signal="confirmed" from="CloseConfirmationDialog" to="." method="_on_close_confirmation_dialog_confirmed"] -[connection signal="custom_action" from="CloseConfirmationDialog" to="." method="_on_close_confirmation_dialog_custom_action"] -[connection signal="result_selected" from="FindInFilesDialog/FindInFiles" to="." method="_on_find_in_files_result_selected"] diff --git a/addons/dialogue_manager/views/settings_view.gd b/addons/dialogue_manager/views/settings_view.gd deleted file mode 100644 index 8ab4e95..0000000 --- a/addons/dialogue_manager/views/settings_view.gd +++ /dev/null @@ -1,280 +0,0 @@ -@tool -extends TabContainer - - -signal script_button_pressed(path: String) - - -const DialogueConstants = preload("../constants.gd") -const DialogueSettings = preload("../settings.gd") - - -enum PathTarget { - CustomTestScene, - Balloon -} - - -# Editor -@onready var new_template_button: CheckBox = $Editor/NewTemplateButton -@onready var characters_translations_button: CheckBox = $Editor/CharactersTranslationsButton -@onready var wrap_lines_button: Button = $Editor/WrapLinesButton -@onready var default_csv_locale: LineEdit = $Editor/DefaultCSVLocale - -# Runtime -@onready var include_all_responses_button: CheckBox = $Runtime/IncludeAllResponsesButton -@onready var ignore_missing_state_values: CheckBox = $Runtime/IgnoreMissingStateValues -@onready var balloon_path_input: LineEdit = $Runtime/CustomBalloon/BalloonPath -@onready var revert_balloon_button: Button = $Runtime/CustomBalloon/RevertBalloonPath -@onready var load_balloon_button: Button = $Runtime/CustomBalloon/LoadBalloonPath -@onready var states_title: Label = $Runtime/StatesTitle -@onready var globals_list: Tree = $Runtime/GlobalsList - -# Advanced -@onready var check_for_updates: CheckBox = $Advanced/CheckForUpdates -@onready var include_characters_in_translations: CheckBox = $Advanced/IncludeCharactersInTranslations -@onready var include_notes_in_translations: CheckBox = $Advanced/IncludeNotesInTranslations -@onready var open_in_external_editor_button: CheckBox = $Advanced/OpenInExternalEditorButton -@onready var test_scene_path_input: LineEdit = $Advanced/CustomTestScene/TestScenePath -@onready var revert_test_scene_button: Button = $Advanced/CustomTestScene/RevertTestScene -@onready var load_test_scene_button: Button = $Advanced/CustomTestScene/LoadTestScene -@onready var custom_test_scene_file_dialog: FileDialog = $CustomTestSceneFileDialog -@onready var create_lines_for_response_characters: CheckBox = $Advanced/CreateLinesForResponseCharacters -@onready var missing_translations_button: CheckBox = $Advanced/MissingTranslationsButton - -var editor_plugin: EditorPlugin -var all_globals: Dictionary = {} -var enabled_globals: Array = [] -var path_target: PathTarget = PathTarget.CustomTestScene - -var _default_test_scene_path: String = preload("../test_scene.tscn").resource_path - -var _recompile_if_changed_settings: Dictionary - - -func _ready() -> void: - new_template_button.text = DialogueConstants.translate(&"settings.new_template") - $Editor/MissingTranslationsHint.text = DialogueConstants.translate(&"settings.missing_keys_hint") - characters_translations_button.text = DialogueConstants.translate(&"settings.characters_translations") - wrap_lines_button.text = DialogueConstants.translate(&"settings.wrap_long_lines") - $Editor/DefaultCSVLocaleLabel.text = DialogueConstants.translate(&"settings.default_csv_locale") - - include_all_responses_button.text = DialogueConstants.translate(&"settings.include_failed_responses") - ignore_missing_state_values.text = DialogueConstants.translate(&"settings.ignore_missing_state_values") - $Runtime/CustomBalloonLabel.text = DialogueConstants.translate(&"settings.default_balloon_hint") - states_title.text = DialogueConstants.translate(&"settings.states_shortcuts") - $Runtime/StatesMessage.text = DialogueConstants.translate(&"settings.states_message") - $Runtime/StatesHint.text = DialogueConstants.translate(&"settings.states_hint") - - check_for_updates.text = DialogueConstants.translate(&"settings.check_for_updates") - include_characters_in_translations.text = DialogueConstants.translate(&"settings.include_characters_in_translations") - include_notes_in_translations.text = DialogueConstants.translate(&"settings.include_notes_in_translations") - open_in_external_editor_button.text = DialogueConstants.translate(&"settings.open_in_external_editor") - $Advanced/ExternalWarning.text = DialogueConstants.translate(&"settings.external_editor_warning") - $Advanced/CustomTestSceneLabel.text = DialogueConstants.translate(&"settings.custom_test_scene") - $Advanced/RecompileWarning.text = DialogueConstants.translate(&"settings.recompile_warning") - missing_translations_button.text = DialogueConstants.translate(&"settings.missing_keys") - create_lines_for_response_characters.text = DialogueConstants.translate(&"settings.create_lines_for_responses_with_characters") - - current_tab = 0 - - -func prepare() -> void: - _recompile_if_changed_settings = _get_settings_that_require_recompilation() - - test_scene_path_input.placeholder_text = DialogueSettings.get_setting("custom_test_scene_path", _default_test_scene_path) - revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path - revert_test_scene_button.icon = get_theme_icon("RotateLeft", "EditorIcons") - revert_test_scene_button.tooltip_text = DialogueConstants.translate(&"settings.revert_to_default_test_scene") - load_test_scene_button.icon = get_theme_icon("Load", "EditorIcons") - - var balloon_path: String = DialogueSettings.get_setting("balloon_path", "") - if not FileAccess.file_exists(balloon_path): - DialogueSettings.set_setting("balloon_path", "") - balloon_path = "" - balloon_path_input.placeholder_text = balloon_path if balloon_path != "" else DialogueConstants.translate(&"settings.default_balloon_path") - revert_balloon_button.visible = balloon_path != "" - revert_balloon_button.icon = get_theme_icon("RotateLeft", "EditorIcons") - revert_balloon_button.tooltip_text = DialogueConstants.translate(&"settings.revert_to_default_balloon") - load_balloon_button.icon = get_theme_icon("Load", "EditorIcons") - - var scale: float = editor_plugin.get_editor_interface().get_editor_scale() - custom_test_scene_file_dialog.min_size = Vector2(600, 500) * scale - - states_title.add_theme_font_override("font", get_theme_font("bold", "EditorFonts")) - - check_for_updates.set_pressed_no_signal(DialogueSettings.get_user_value("check_for_updates", true)) - characters_translations_button.set_pressed_no_signal(DialogueSettings.get_setting("export_characters_in_translation", true)) - wrap_lines_button.set_pressed_no_signal(DialogueSettings.get_setting("wrap_lines", false)) - include_all_responses_button.set_pressed_no_signal(DialogueSettings.get_setting("include_all_responses", false)) - ignore_missing_state_values.set_pressed_no_signal(DialogueSettings.get_setting("ignore_missing_state_values", false)) - new_template_button.set_pressed_no_signal(DialogueSettings.get_setting("new_with_template", true)) - default_csv_locale.text = DialogueSettings.get_setting("default_csv_locale", "en") - - missing_translations_button.set_pressed_no_signal(DialogueSettings.get_setting("missing_translations_are_errors", false)) - create_lines_for_response_characters.set_pressed_no_signal(DialogueSettings.get_setting("create_lines_for_responses_with_characters", true)) - - include_characters_in_translations.set_pressed_no_signal(DialogueSettings.get_setting("include_character_in_translation_exports", false)) - include_notes_in_translations.set_pressed_no_signal(DialogueSettings.get_setting("include_notes_in_translation_exports", false)) - open_in_external_editor_button.set_pressed_no_signal(DialogueSettings.get_user_value("open_in_external_editor", false)) - - var editor_settings: EditorSettings = editor_plugin.get_editor_interface().get_editor_settings() - var external_editor: String = editor_settings.get_setting("text_editor/external/exec_path") - var use_external_editor: bool = editor_settings.get_setting("text_editor/external/use_external_editor") and external_editor != "" - if not use_external_editor: - open_in_external_editor_button.hide() - $Advanced/ExternalWarning.hide() - $Advanced/ExternalSeparator.hide() - - var project = ConfigFile.new() - var err = project.load("res://project.godot") - assert(err == OK, "Could not find the project file") - - all_globals.clear() - if project.has_section("autoload"): - for key in project.get_section_keys("autoload"): - if key != "DialogueManager": - all_globals[key] = project.get_value("autoload", key) - - enabled_globals = DialogueSettings.get_setting("states", []).duplicate() - globals_list.clear() - var root = globals_list.create_item() - for name in all_globals.keys(): - var item: TreeItem = globals_list.create_item(root) - item.set_cell_mode(0, TreeItem.CELL_MODE_CHECK) - item.set_checked(0, name in enabled_globals) - item.set_text(0, name) - item.add_button(1, get_theme_icon("Edit", "EditorIcons")) - item.set_text(2, all_globals.get(name, "").replace("*res://", "res://")) - - globals_list.set_column_expand(0, false) - globals_list.set_column_custom_minimum_width(0, 250) - globals_list.set_column_expand(1, false) - globals_list.set_column_custom_minimum_width(1, 40) - globals_list.set_column_titles_visible(true) - globals_list.set_column_title(0, DialogueConstants.translate(&"settings.autoload")) - globals_list.set_column_title(1, "") - globals_list.set_column_title(2, DialogueConstants.translate(&"settings.path")) - - -func apply_settings_changes() -> void: - if _recompile_if_changed_settings != _get_settings_that_require_recompilation(): - Engine.get_meta("DialogueCache").reimport_files() - - -func _get_settings_that_require_recompilation() -> Dictionary: - return DialogueSettings.get_settings([ - "missing_translations_are_errors", - "create_lines_for_responses_with_characters" - ]) - - -### Signals - - -func _on_missing_translations_button_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("missing_translations_are_errors", toggled_on) - - -func _on_characters_translations_button_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("export_characters_in_translation", toggled_on) - - -func _on_wrap_lines_button_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("wrap_lines", toggled_on) - - -func _on_include_all_responses_button_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("include_all_responses", toggled_on) - - -func _on_globals_list_item_selected() -> void: - var item = globals_list.get_selected() - var is_checked = not item.is_checked(0) - item.set_checked(0, is_checked) - - if is_checked: - enabled_globals.append(item.get_text(0)) - else: - enabled_globals.erase(item.get_text(0)) - - DialogueSettings.set_setting("states", enabled_globals) - - -func _on_globals_list_button_clicked(item: TreeItem, column: int, id: int, mouse_button_index: int) -> void: - emit_signal("script_button_pressed", item.get_text(2)) - - -func _on_sample_template_toggled(toggled_on): - DialogueSettings.set_setting("new_with_template", toggled_on) - - -func _on_revert_test_scene_pressed() -> void: - DialogueSettings.set_setting("custom_test_scene_path", _default_test_scene_path) - test_scene_path_input.placeholder_text = _default_test_scene_path - revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path - - -func _on_load_test_scene_pressed() -> void: - path_target = PathTarget.CustomTestScene - custom_test_scene_file_dialog.popup_centered() - - -func _on_custom_test_scene_file_dialog_file_selected(path: String) -> void: - match path_target: - PathTarget.CustomTestScene: - # Check that the test scene is a subclass of BaseDialogueTestScene - var test_scene: PackedScene = load(path) - if test_scene and test_scene.instantiate() is BaseDialogueTestScene: - DialogueSettings.set_setting("custom_test_scene_path", path) - test_scene_path_input.placeholder_text = path - revert_test_scene_button.visible = test_scene_path_input.placeholder_text != _default_test_scene_path - else: - var accept: AcceptDialog = AcceptDialog.new() - accept.dialog_text = DialogueConstants.translate(&"settings.invalid_test_scene").format({ path = path }) - add_child(accept) - accept.popup_centered.call_deferred() - - PathTarget.Balloon: - DialogueSettings.set_setting("balloon_path", path) - balloon_path_input.placeholder_text = path - revert_balloon_button.visible = balloon_path_input.placeholder_text != "" - - -func _on_ignore_missing_state_values_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("ignore_missing_state_values", toggled_on) - - -func _on_default_csv_locale_text_changed(new_text: String) -> void: - DialogueSettings.set_setting("default_csv_locale", new_text) - - -func _on_revert_balloon_path_pressed() -> void: - DialogueSettings.set_setting("balloon_path", "") - balloon_path_input.placeholder_text = DialogueConstants.translate(&"settings.default_balloon_path") - revert_balloon_button.visible = DialogueSettings.get_setting("balloon_path", "") != "" - - -func _on_load_balloon_path_pressed() -> void: - path_target = PathTarget.Balloon - custom_test_scene_file_dialog.popup_centered() - - -func _on_create_lines_for_response_characters_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("create_lines_for_responses_with_characters", toggled_on) - - -func _on_open_in_external_editor_button_toggled(toggled_on: bool) -> void: - DialogueSettings.set_user_value("open_in_external_editor", toggled_on) - - -func _on_include_characters_in_translations_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("include_character_in_translation_exports", toggled_on) - - -func _on_include_notes_in_translations_toggled(toggled_on: bool) -> void: - DialogueSettings.set_setting("include_notes_in_translation_exports", toggled_on) - - -func _on_keep_up_to_date_toggled(toggled_on: bool) -> void: - DialogueSettings.set_user_value("check_for_updates", toggled_on) diff --git a/addons/dialogue_manager/views/settings_view.tscn b/addons/dialogue_manager/views/settings_view.tscn deleted file mode 100644 index 09df0a2..0000000 --- a/addons/dialogue_manager/views/settings_view.tscn +++ /dev/null @@ -1,221 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://cpg4lg1r3ff6m"] - -[ext_resource type="Script" path="res://addons/dialogue_manager/views/settings_view.gd" id="1_06uxa"] - -[sub_resource type="Theme" id="Theme_3a8rc"] -HSeparator/constants/separation = 20 - -[node name="SettingsView" type="TabContainer"] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_right = -206.0 -offset_bottom = -345.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -theme = SubResource("Theme_3a8rc") -current_tab = 2 -script = ExtResource("1_06uxa") - -[node name="Editor" type="VBoxContainer" parent="."] -visible = false -layout_mode = 2 - -[node name="NewTemplateButton" type="CheckBox" parent="Editor"] -layout_mode = 2 -button_pressed = true -text = "New dialogue files will start with template text" - -[node name="MissingTranslationsHint" type="Label" parent="Editor"] -modulate = Color(1, 1, 1, 0.501961) -custom_minimum_size = Vector2(10, 0) -layout_mode = 2 -text = "If you are using static translation keys then having this enabled will help you find any lines that you haven't added a key to yet." -autowrap_mode = 3 - -[node name="CharactersTranslationsButton" type="CheckBox" parent="Editor"] -layout_mode = 2 -button_pressed = true -text = "Export character names in translation files" - -[node name="WrapLinesButton" type="CheckBox" parent="Editor"] -layout_mode = 2 -button_pressed = true -text = "Wrap long lines" - -[node name="HSeparator" type="HSeparator" parent="Editor"] -layout_mode = 2 - -[node name="DefaultCSVLocaleLabel" type="Label" parent="Editor"] -layout_mode = 2 -text = "Default CSV Locale" - -[node name="DefaultCSVLocale" type="LineEdit" parent="Editor"] -layout_mode = 2 - -[node name="Runtime" type="VBoxContainer" parent="."] -visible = false -layout_mode = 2 - -[node name="IncludeAllResponsesButton" type="CheckBox" parent="Runtime"] -layout_mode = 2 -text = "Include responses with failed conditions" - -[node name="IgnoreMissingStateValues" type="CheckBox" parent="Runtime"] -layout_mode = 2 -text = "Skip over missing state value errors (not recommended)" - -[node name="HSeparator" type="HSeparator" parent="Runtime"] -layout_mode = 2 - -[node name="CustomBalloonLabel" type="Label" parent="Runtime"] -layout_mode = 2 -text = "Custom balloon to use when calling \"DialogueManager.show_balloon()\"" - -[node name="CustomBalloon" type="HBoxContainer" parent="Runtime"] -layout_mode = 2 - -[node name="BalloonPath" type="LineEdit" parent="Runtime/CustomBalloon"] -layout_mode = 2 -size_flags_horizontal = 3 -focus_mode = 0 -editable = false -shortcut_keys_enabled = false -middle_mouse_paste_enabled = false - -[node name="RevertBalloonPath" type="Button" parent="Runtime/CustomBalloon"] -visible = false -layout_mode = 2 -tooltip_text = "Revert to default test scene" -flat = true - -[node name="LoadBalloonPath" type="Button" parent="Runtime/CustomBalloon"] -layout_mode = 2 - -[node name="HSeparator2" type="HSeparator" parent="Runtime"] -layout_mode = 2 - -[node name="StatesTitle" type="Label" parent="Runtime"] -layout_mode = 2 -text = "State Shortcuts" - -[node name="StatesMessage" type="Label" parent="Runtime"] -layout_mode = 2 -text = "If an autoload is enabled here you can refer to its properties and methods without having to use its name." - -[node name="StatesHint" type="Label" parent="Runtime"] -modulate = Color(1, 1, 1, 0.501961) -custom_minimum_size = Vector2(10, 0) -layout_mode = 2 -text = "ie. Instead of \"SomeState.some_property\" you could just use \"some_property\"" -autowrap_mode = 3 - -[node name="GlobalsList" type="Tree" parent="Runtime"] -layout_mode = 2 -size_flags_vertical = 3 -columns = 3 -column_titles_visible = true -allow_reselect = true -hide_folding = true -hide_root = true -select_mode = 1 - -[node name="Advanced" type="VBoxContainer" parent="."] -layout_mode = 2 - -[node name="CheckForUpdates" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Check for updates" - -[node name="HSeparator" type="HSeparator" parent="Advanced"] -layout_mode = 2 - -[node name="IncludeCharactersInTranslations" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Include character names in translation exports" - -[node name="IncludeNotesInTranslations" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Include notes (## comments) in translation exports" - -[node name="ExternalSeparator" type="HSeparator" parent="Advanced"] -layout_mode = 2 - -[node name="OpenInExternalEditorButton" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Open dialogue files in external editor" - -[node name="ExternalWarning" type="Label" parent="Advanced"] -layout_mode = 2 -text = "Note: Syntax highlighting and detailed error checking are not supported in external editors." - -[node name="HSeparator3" type="HSeparator" parent="Advanced"] -layout_mode = 2 - -[node name="CustomTestSceneLabel" type="Label" parent="Advanced"] -layout_mode = 2 -text = "Custom test scene (must extend BaseDialogueTestScene)" - -[node name="CustomTestScene" type="HBoxContainer" parent="Advanced"] -layout_mode = 2 - -[node name="TestScenePath" type="LineEdit" parent="Advanced/CustomTestScene"] -layout_mode = 2 -size_flags_horizontal = 3 -focus_mode = 0 -placeholder_text = "res://addons/dialogue_manager/test_scene.tscn" -editable = false -shortcut_keys_enabled = false -middle_mouse_paste_enabled = false - -[node name="RevertTestScene" type="Button" parent="Advanced/CustomTestScene"] -visible = false -layout_mode = 2 -tooltip_text = "Revert to default test scene" -flat = true - -[node name="LoadTestScene" type="Button" parent="Advanced/CustomTestScene"] -layout_mode = 2 - -[node name="HSeparator4" type="HSeparator" parent="Advanced"] -layout_mode = 2 - -[node name="RecompileWarning" type="Label" parent="Advanced"] -layout_mode = 2 -text = "Changing these settings will force a recompile of all dialogue. Only change them if you know what you are doing." - -[node name="MissingTranslationsButton" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Treat missing translation keys as errors" - -[node name="CreateLinesForResponseCharacters" type="CheckBox" parent="Advanced"] -layout_mode = 2 -text = "Create child dialogue line for responses with character names in them" - -[node name="CustomTestSceneFileDialog" type="FileDialog" parent="."] -title = "Open a File" -ok_button_text = "Open" -file_mode = 0 -filters = PackedStringArray("*.tscn ; Scene") - -[connection signal="toggled" from="Editor/NewTemplateButton" to="." method="_on_sample_template_toggled"] -[connection signal="toggled" from="Editor/CharactersTranslationsButton" to="." method="_on_characters_translations_button_toggled"] -[connection signal="toggled" from="Editor/WrapLinesButton" to="." method="_on_wrap_lines_button_toggled"] -[connection signal="text_changed" from="Editor/DefaultCSVLocale" to="." method="_on_default_csv_locale_text_changed"] -[connection signal="toggled" from="Runtime/IncludeAllResponsesButton" to="." method="_on_include_all_responses_button_toggled"] -[connection signal="toggled" from="Runtime/IgnoreMissingStateValues" to="." method="_on_ignore_missing_state_values_toggled"] -[connection signal="pressed" from="Runtime/CustomBalloon/RevertBalloonPath" to="." method="_on_revert_balloon_path_pressed"] -[connection signal="pressed" from="Runtime/CustomBalloon/LoadBalloonPath" to="." method="_on_load_balloon_path_pressed"] -[connection signal="button_clicked" from="Runtime/GlobalsList" to="." method="_on_globals_list_button_clicked"] -[connection signal="item_selected" from="Runtime/GlobalsList" to="." method="_on_globals_list_item_selected"] -[connection signal="toggled" from="Advanced/CheckForUpdates" to="." method="_on_keep_up_to_date_toggled"] -[connection signal="toggled" from="Advanced/IncludeCharactersInTranslations" to="." method="_on_include_characters_in_translations_toggled"] -[connection signal="toggled" from="Advanced/IncludeNotesInTranslations" to="." method="_on_include_notes_in_translations_toggled"] -[connection signal="toggled" from="Advanced/OpenInExternalEditorButton" to="." method="_on_open_in_external_editor_button_toggled"] -[connection signal="pressed" from="Advanced/CustomTestScene/RevertTestScene" to="." method="_on_revert_test_scene_pressed"] -[connection signal="pressed" from="Advanced/CustomTestScene/LoadTestScene" to="." method="_on_load_test_scene_pressed"] -[connection signal="toggled" from="Advanced/MissingTranslationsButton" to="." method="_on_missing_translations_button_toggled"] -[connection signal="toggled" from="Advanced/CreateLinesForResponseCharacters" to="." method="_on_create_lines_for_response_characters_toggled"] -[connection signal="file_selected" from="CustomTestSceneFileDialog" to="." method="_on_custom_test_scene_file_dialog_file_selected"] From 52a1881a1c27e9591ad6fcf68455b82b174d37f8 Mon Sep 17 00:00:00 2001 From: JUB-Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 14:30:55 -0400 Subject: [PATCH 53/86] working on maze gdd --- The Maze.md | 66 ---------------------------------------------- src/main/main.tscn | 3 +++ the_maze.md | 31 ++++++++++++++++++++++ 3 files changed, 34 insertions(+), 66 deletions(-) delete mode 100644 The Maze.md create mode 100644 the_maze.md diff --git a/The Maze.md b/The Maze.md deleted file mode 100644 index ceecaf5..0000000 --- a/The Maze.md +++ /dev/null @@ -1,66 +0,0 @@ -# To do -Levels (easy to make) -## puzzle ideas -Every code is unique -combo puzzle (3 or 4 inputs) -missing rooms (you go from 22 to 24 and you're like oh where 23?) -backtracking to solve in another room -giving items to NPCs (you unlock shit from other rooms and give it to other NPCs) -rooms in jumbled order (1 -> 7 -> 12 -> 3) -#### binary type code -1. Binary code history hud -2. Are we expecting the player to know this or do we teach them -3. How do we communicate this to the player -# Ignore everything below -## Main Gameplay loop -Puzzle RPG -interacting with NPCs and using their info to solve puzzles while also fighting enemies using grid movement turn based combat (similar to crypt of the necrodancer) and might have magic spells, might. -## Verbs (mechanics) -Movement before boots -Interacting (z) -Movement after boots: 8 different types of sound 4 of them -move one time the other move a second time -## in the talks -melee combat -### can be scrapped -spells -take off boots -## To Do -## Game -What type of sounds do we want? 8 notes on a scale from a particular sound can be an instrument -How de we translate to the player what the sounds do? Chests tell you? should be done in first room? -How many rooms in total? 6 rooms excluding tutorial room -## Enemies -Cows (Chests hate them cause they moo and smell) -Bees (Chests are scared of them cause they sting) -Chests won't talk to you unless you defeat them -## Rooms -Every room has a chest no matter what -### Tutorial Room -How the song boots work? -### Room 1 -1 cow? -### Room 2 -1 bee? -### Room 3 -1 cow 1 bee? -### Room 4 -1 cow 2 bees? -### Room 5 -lying chests? -### Room 6 (extra room) -you fell for the lying chest -your reward: 2 cows 3 bees -### Spells -stun: stuns enemies -buff: gives you more movement -talk to chest: you talk to chest -## Lore -### All chests have song boots -They see you already have them on so they talk to you -### Why are the chests talking? -Because the developer played souls dark and there was a message with "friend ahead" prompt in front of a mimic and thought that she wanted to be friends with the mimics -### The boots overheat you gonna take em off - -### Why song boots? -The golden piece will give you a way but an unconventional way diff --git a/src/main/main.tscn b/src/main/main.tscn index 0da652a..de4db7b 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -90,3 +90,6 @@ theme_override_colors/font_color = Color(0, 0, 0, 1) theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "B00" + +[node name="Player2" parent="." instance=ExtResource("2_ekt33")] +position = Vector2(130, 47) diff --git a/the_maze.md b/the_maze.md new file mode 100644 index 0000000..fea9ca5 --- /dev/null +++ b/the_maze.md @@ -0,0 +1,31 @@ +# The Maze GDD + +## What is The Maze? +The maze is a non linear narritive puzzle game. + +## Moment to Moment Gameplay +- Navigate rooms +- Talk to NPCs +- Give/Recieve Items +- Enter boot codes + +## Solution concepts +### Songboots +- Use your songboots to enter unique movement based codes. This is the primary puzzle solving method + +#### Codes have unique effects: +- Sending you to a specific or relative room (send to room 10, or to 5 rooms past where you currently are) either immedetly or make stairs that send you there + +- Giving you items, or making items appear somewhere in the Maze + +- There are also Special codes that can only be entered at certain rooms: like a code that lets you enter a number in binary + +### Information from NPCs +- talk to things (people, chests, cows and bees?) and figure out what to do based on that + + + +## puzzle concepts +- missing rooms (you go from 22 to 24 and you're like oh where 23?) +- backtracking to solve in another room +- giving items to NPCs (you unlock shit from other rooms and give it to other NPCs) From 6e8e29cd073f713cc42844e8681f5d94927bd3e4 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 15:09:40 -0400 Subject: [PATCH 54/86] wrote out gdd --- the_maze.md | 58 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/the_maze.md b/the_maze.md index fea9ca5..5292ea9 100644 --- a/the_maze.md +++ b/the_maze.md @@ -1,31 +1,49 @@ # The Maze GDD ## What is The Maze? -The maze is a non linear narritive puzzle game. +The maze is a non linear 2d Grid-based narrative puzzle game. +Connect disparate information and piece together not only the secrets of this maze but also a way to escape. ## Moment to Moment Gameplay -- Navigate rooms -- Talk to NPCs -- Give/Recieve Items -- Enter boot codes +- The game is based in screen sized rooms. Go to stairs to travel to another room, the Rooms eventually loop around on themselves. (or maybe getting back to the top requires a movement code?) +- Talk to NPCs in the rooms to learn important information +- Give/Receive Items to/from NPCs and other things in the environment, Players will have a simple inventory with one item equipable at a time. +- Solve puzzles +- Enter boot codes, your movements are recorded, certain movement patterns do things. -## Solution concepts +## Puzzle solving tools ### Songboots -- Use your songboots to enter unique movement based codes. This is the primary puzzle solving method - -#### Codes have unique effects: -- Sending you to a specific or relative room (send to room 10, or to 5 rooms past where you currently are) either immedetly or make stairs that send you there +- Use your Songboots to enter unique movement based codes. Most puzzles will be solved by you figuring out the correct movement code needed +- You can move in 4 cardinal directions, each direction playing a note moving twice in the same direction will play a different note, 8 notes in total, one octave. +#### Code effects: +- Sending you to a specific or relative room (send to room 10, or to 5 rooms past where you currently are) either immediately or make stairs that send you there - Giving you items, or making items appear somewhere in the Maze - -- There are also Special codes that can only be entered at certain rooms: like a code that lets you enter a number in binary +- Codes that can only be entered at certain rooms: like a code that lets you enter a number in binary only when used in a certain room ### Information from NPCs -- talk to things (people, chests, cows and bees?) and figure out what to do based on that - - - -## puzzle concepts -- missing rooms (you go from 22 to 24 and you're like oh where 23?) -- backtracking to solve in another room -- giving items to NPCs (you unlock shit from other rooms and give it to other NPCs) +- Talk to things (people, chests, cows and bees?) and figure out what to do based on that +- Items can be received from NPCs + +#### NPC item types: +- Items that you can give to other NPCs to advance a quest-line +- Items that are temporary or only exist for a limited time (cow's milk that goes bad after a certain number of "mooooves") +- Items that are able to be placed in certain areas (finding a statue and putting a jewel inside it) + + +## Puzzle Ideas we came up with: +- The Maze floors skip over a room (goes from 22 to 24, skipping 23). You need to discover a method of navigation other then going down stairs to be able to travel there. +- Songboot codes delivered though song, with the notes the NPC sings being notes you can play with certain movements +- A logic puzzle with 3 chests, all of them making some accusation about the others lying. Decern which one is telling the truth and open that one + - maybe opening the wrong chests sends you to a random floor? +- Using Items that are findable after the relevant NPC appears, requiring you to wrap around and give it to them +- Chests that are connected? so putting an item inside one will let you retrieve it from another (could be a solution to the milk spoiling idea) +- an NPC who seems to know more then they're letting on sharing secrets about how to navigate the maze (what is their deal) + +## Lore, Story, and Context +### Questions that need to be answered: +- The Maze itself: who what where when why how +- who is the player, what is their goal +- who are the NPCs, what are their goals +- why boots, why sounds +- The golden piece, How should the game end? From e8f8230008d3a159d6af2c0a1012c7a7d2c02ea7 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 15:30:21 -0400 Subject: [PATCH 55/86] obsidian vault, didn't track any of the hidden files --- docs/the-maze-vault/.gitignore | 1 + docs/the-maze-vault/Welcome.md | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 docs/the-maze-vault/.gitignore create mode 100644 docs/the-maze-vault/Welcome.md diff --git a/docs/the-maze-vault/.gitignore b/docs/the-maze-vault/.gitignore new file mode 100644 index 0000000..1036bd2 --- /dev/null +++ b/docs/the-maze-vault/.gitignore @@ -0,0 +1 @@ +.obsidian/ \ No newline at end of file diff --git a/docs/the-maze-vault/Welcome.md b/docs/the-maze-vault/Welcome.md new file mode 100644 index 0000000..f9bca28 --- /dev/null +++ b/docs/the-maze-vault/Welcome.md @@ -0,0 +1,5 @@ +This is your new *vault*. + +Make a note of something, [[create a link]], or try [the Importer](https://help.obsidian.md/Plugins/Importer)! + +When you're ready, delete this note and make the vault your own. \ No newline at end of file From e5374ddc5cf134ce176144ed55d4d7cbcfff841c Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 15:32:35 -0400 Subject: [PATCH 56/86] moved gdd to obsidian --- docs/the-maze-vault/design_document.md | 49 ++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 docs/the-maze-vault/design_document.md diff --git a/docs/the-maze-vault/design_document.md b/docs/the-maze-vault/design_document.md new file mode 100644 index 0000000..5292ea9 --- /dev/null +++ b/docs/the-maze-vault/design_document.md @@ -0,0 +1,49 @@ +# The Maze GDD + +## What is The Maze? +The maze is a non linear 2d Grid-based narrative puzzle game. +Connect disparate information and piece together not only the secrets of this maze but also a way to escape. + +## Moment to Moment Gameplay +- The game is based in screen sized rooms. Go to stairs to travel to another room, the Rooms eventually loop around on themselves. (or maybe getting back to the top requires a movement code?) +- Talk to NPCs in the rooms to learn important information +- Give/Receive Items to/from NPCs and other things in the environment, Players will have a simple inventory with one item equipable at a time. +- Solve puzzles +- Enter boot codes, your movements are recorded, certain movement patterns do things. + +## Puzzle solving tools +### Songboots +- Use your Songboots to enter unique movement based codes. Most puzzles will be solved by you figuring out the correct movement code needed +- You can move in 4 cardinal directions, each direction playing a note moving twice in the same direction will play a different note, 8 notes in total, one octave. + +#### Code effects: +- Sending you to a specific or relative room (send to room 10, or to 5 rooms past where you currently are) either immediately or make stairs that send you there +- Giving you items, or making items appear somewhere in the Maze +- Codes that can only be entered at certain rooms: like a code that lets you enter a number in binary only when used in a certain room + +### Information from NPCs +- Talk to things (people, chests, cows and bees?) and figure out what to do based on that +- Items can be received from NPCs + +#### NPC item types: +- Items that you can give to other NPCs to advance a quest-line +- Items that are temporary or only exist for a limited time (cow's milk that goes bad after a certain number of "mooooves") +- Items that are able to be placed in certain areas (finding a statue and putting a jewel inside it) + + +## Puzzle Ideas we came up with: +- The Maze floors skip over a room (goes from 22 to 24, skipping 23). You need to discover a method of navigation other then going down stairs to be able to travel there. +- Songboot codes delivered though song, with the notes the NPC sings being notes you can play with certain movements +- A logic puzzle with 3 chests, all of them making some accusation about the others lying. Decern which one is telling the truth and open that one + - maybe opening the wrong chests sends you to a random floor? +- Using Items that are findable after the relevant NPC appears, requiring you to wrap around and give it to them +- Chests that are connected? so putting an item inside one will let you retrieve it from another (could be a solution to the milk spoiling idea) +- an NPC who seems to know more then they're letting on sharing secrets about how to navigate the maze (what is their deal) + +## Lore, Story, and Context +### Questions that need to be answered: +- The Maze itself: who what where when why how +- who is the player, what is their goal +- who are the NPCs, what are their goals +- why boots, why sounds +- The golden piece, How should the game end? From a83611c60f739f22d82faceae300363526891e12 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 15:33:09 -0400 Subject: [PATCH 57/86] I should review that thing that lets you combine commits --- the_maze.md | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 the_maze.md diff --git a/the_maze.md b/the_maze.md deleted file mode 100644 index 5292ea9..0000000 --- a/the_maze.md +++ /dev/null @@ -1,49 +0,0 @@ -# The Maze GDD - -## What is The Maze? -The maze is a non linear 2d Grid-based narrative puzzle game. -Connect disparate information and piece together not only the secrets of this maze but also a way to escape. - -## Moment to Moment Gameplay -- The game is based in screen sized rooms. Go to stairs to travel to another room, the Rooms eventually loop around on themselves. (or maybe getting back to the top requires a movement code?) -- Talk to NPCs in the rooms to learn important information -- Give/Receive Items to/from NPCs and other things in the environment, Players will have a simple inventory with one item equipable at a time. -- Solve puzzles -- Enter boot codes, your movements are recorded, certain movement patterns do things. - -## Puzzle solving tools -### Songboots -- Use your Songboots to enter unique movement based codes. Most puzzles will be solved by you figuring out the correct movement code needed -- You can move in 4 cardinal directions, each direction playing a note moving twice in the same direction will play a different note, 8 notes in total, one octave. - -#### Code effects: -- Sending you to a specific or relative room (send to room 10, or to 5 rooms past where you currently are) either immediately or make stairs that send you there -- Giving you items, or making items appear somewhere in the Maze -- Codes that can only be entered at certain rooms: like a code that lets you enter a number in binary only when used in a certain room - -### Information from NPCs -- Talk to things (people, chests, cows and bees?) and figure out what to do based on that -- Items can be received from NPCs - -#### NPC item types: -- Items that you can give to other NPCs to advance a quest-line -- Items that are temporary or only exist for a limited time (cow's milk that goes bad after a certain number of "mooooves") -- Items that are able to be placed in certain areas (finding a statue and putting a jewel inside it) - - -## Puzzle Ideas we came up with: -- The Maze floors skip over a room (goes from 22 to 24, skipping 23). You need to discover a method of navigation other then going down stairs to be able to travel there. -- Songboot codes delivered though song, with the notes the NPC sings being notes you can play with certain movements -- A logic puzzle with 3 chests, all of them making some accusation about the others lying. Decern which one is telling the truth and open that one - - maybe opening the wrong chests sends you to a random floor? -- Using Items that are findable after the relevant NPC appears, requiring you to wrap around and give it to them -- Chests that are connected? so putting an item inside one will let you retrieve it from another (could be a solution to the milk spoiling idea) -- an NPC who seems to know more then they're letting on sharing secrets about how to navigate the maze (what is their deal) - -## Lore, Story, and Context -### Questions that need to be answered: -- The Maze itself: who what where when why how -- who is the player, what is their goal -- who are the NPCs, what are their goals -- why boots, why sounds -- The golden piece, How should the game end? From 0dd32f7ab5758aff5e064ae03fbc33ae66a116d2 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 15:49:28 -0400 Subject: [PATCH 58/86] added a rule --- docs/the-maze-vault/valut_rules.md.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docs/the-maze-vault/valut_rules.md.md diff --git a/docs/the-maze-vault/valut_rules.md.md b/docs/the-maze-vault/valut_rules.md.md new file mode 100644 index 0000000..a0eace0 --- /dev/null +++ b/docs/the-maze-vault/valut_rules.md.md @@ -0,0 +1,2 @@ +# rules to keep the vault clean +- please keep all file names snake_case \ No newline at end of file From a5f3740bb57a51110202063bafd37e2d6e98c5bb Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 13 Apr 2024 19:53:20 -0400 Subject: [PATCH 59/86] item database and resources --- assets/dialogue_boxes/balloon.gd | 141 ++++++++++++++++++++++ assets/dialogue_boxes/balloon.tscn | 176 ++++++++++++++++++++++++++++ assets/dialogue_boxes/balloon2.tscn | 176 ++++++++++++++++++++++++++++ assets/equipped-icon.png | Bin 0 -> 162 bytes assets/equipped-icon.png.import | 34 ++++++ assets/item_icons/x.png | Bin 0 -> 201 bytes assets/item_icons/x.png.import | 34 ++++++ assets/ui_themes/new_theme.tres | 16 +++ project.godot | 17 ++- src/autoloads/player_state.gd | 18 +-- src/items/item_db.gd | 29 +++++ src/items/item_res.gd | 14 +++ src/items/test_item.tres | 9 ++ src/main/main.tscn | 74 ++++++++++-- src/main/ui.gd | 6 +- src/player/player.gd | 2 +- src/scene-tiles/chest/chest.gd | 7 +- todo.md | 17 +++ 18 files changed, 742 insertions(+), 28 deletions(-) create mode 100644 assets/dialogue_boxes/balloon.gd create mode 100644 assets/dialogue_boxes/balloon.tscn create mode 100644 assets/dialogue_boxes/balloon2.tscn create mode 100644 assets/equipped-icon.png create mode 100644 assets/equipped-icon.png.import create mode 100644 assets/item_icons/x.png create mode 100644 assets/item_icons/x.png.import create mode 100644 assets/ui_themes/new_theme.tres create mode 100644 src/items/item_db.gd create mode 100644 src/items/item_res.gd create mode 100644 src/items/test_item.tres create mode 100644 todo.md diff --git a/assets/dialogue_boxes/balloon.gd b/assets/dialogue_boxes/balloon.gd new file mode 100644 index 0000000..875e52f --- /dev/null +++ b/assets/dialogue_boxes/balloon.gd @@ -0,0 +1,141 @@ +extends CanvasLayer + +## 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" + +@onready var balloon: Control = %Balloon +@onready var character_label: RichTextLabel = %CharacterLabel +@onready var dialogue_label: DialogueLabel = %DialogueLabel +@onready var responses_menu: DialogueResponsesMenu = %ResponsesMenu + +## 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 + +## The current line +var dialogue_line: DialogueLine: + set(next_dialogue_line): + is_waiting_for_input = false + balloon.focus_mode = Control.FOCUS_ALL + balloon.grab_focus() + + # The dialogue has finished so close the balloon + if not next_dialogue_line: + queue_free() + return + + # If the node isn't ready yet then none of the labels will be ready yet either + if not is_node_ready(): + await ready + + dialogue_line = next_dialogue_line + + 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.set_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() + get: + return dialogue_line + + +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 + + +func _unhandled_input(_event: InputEvent) -> void: + # Only the balloon is allowed to handle input while it's showing + get_viewport().set_input_as_handled() + + +## 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) + + +## 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) + + +### Signals + + +func _on_mutated(_mutation: Dictionary) -> void: + is_waiting_for_input = false + will_hide_balloon = true + get_tree().create_timer(0.1).timeout.connect(func(): + if will_hide_balloon: + will_hide_balloon = false + balloon.hide() + ) + + +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 _on_responses_menu_response_selected(response: DialogueResponse) -> void: + next(response.next_id) diff --git a/assets/dialogue_boxes/balloon.tscn b/assets/dialogue_boxes/balloon.tscn new file mode 100644 index 0000000..8f8f106 --- /dev/null +++ b/assets/dialogue_boxes/balloon.tscn @@ -0,0 +1,176 @@ +[gd_scene load_steps=11 format=3 uid="uid://13s5spsk34qu"] + +[ext_resource type="Script" path="res://assets/dialogue_boxes/balloon.gd" id="1_s2gbs"] +[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_hfvdi"] +[ext_resource type="Theme" uid="uid://eyq5i2mlpkwn" path="res://assets/ui_themes/new_theme.tres" id="2_ui2vm"] +[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_menu.gd" id="3_1j1j0"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_235ry"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.345098, 0.345098, 0.345098, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ufjut"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.227451, 0.227451, 0.227451, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(1, 1, 1, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fcbqo"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_t6i7a"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uy0d5"] +bg_color = Color(0, 0, 0, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="Theme" id="Theme_qq3yp"] +default_font_size = 8 +Button/styles/disabled = SubResource("StyleBoxFlat_235ry") +Button/styles/focus = SubResource("StyleBoxFlat_ufjut") +Button/styles/hover = SubResource("StyleBoxFlat_fcbqo") +Button/styles/normal = SubResource("StyleBoxFlat_t6i7a") +MarginContainer/constants/margin_bottom = 4 +MarginContainer/constants/margin_left = 8 +MarginContainer/constants/margin_right = 8 +MarginContainer/constants/margin_top = 4 +Panel/styles/panel = SubResource("StyleBoxFlat_uy0d5") + +[node name="ExampleBalloon" type="CanvasLayer"] +layer = 100 +script = ExtResource("1_s2gbs") +next_action = &"adv_txt" +skip_action = &"cancel_txt" + +[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"] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 1.0 +offset_top = -43.0 +grow_horizontal = 2 +grow_vertical = 0 +theme = ExtResource("2_ui2vm") + +[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 +theme = ExtResource("2_ui2vm") + +[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.498039) +layout_mode = 2 +mouse_filter = 1 +bbcode_enabled = true +text = "Character" +fit_content = true +scroll_active = false + +[node name="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("2_hfvdi")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +text = "Dialogue..." + +[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 = -124.0 +offset_top = -218.0 +offset_right = 125.0 +offset_bottom = -50.0 +grow_horizontal = 2 +grow_vertical = 0 +theme = ExtResource("2_ui2vm") + +[node name="ResponsesMenu" type="VBoxContainer" parent="Balloon/Responses"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 8 +theme_override_constants/separation = 2 +script = ExtResource("3_1j1j0") + +[node name="ResponseExample" type="Button" parent="Balloon/Responses/ResponsesMenu"] +layout_mode = 2 +text = "Response Example" + +[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"] diff --git a/assets/dialogue_boxes/balloon2.tscn b/assets/dialogue_boxes/balloon2.tscn new file mode 100644 index 0000000..18be933 --- /dev/null +++ b/assets/dialogue_boxes/balloon2.tscn @@ -0,0 +1,176 @@ +[gd_scene load_steps=11 format=3 uid="uid://blwpjecivsqli"] + +[ext_resource type="Script" path="res://assets/dialogue_boxes/balloon.gd" id="1_wmucd"] +[ext_resource type="Theme" uid="uid://eyq5i2mlpkwn" path="res://assets/ui_themes/new_theme.tres" id="2_i6ssm"] +[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="3_np1qn"] +[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_menu.gd" id="4_qcru4"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_235ry"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.345098, 0.345098, 0.345098, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ufjut"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.227451, 0.227451, 0.227451, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(1, 1, 1, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fcbqo"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_t6i7a"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uy0d5"] +bg_color = Color(0, 0, 0, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="Theme" id="Theme_qq3yp"] +default_font_size = 8 +Button/styles/disabled = SubResource("StyleBoxFlat_235ry") +Button/styles/focus = SubResource("StyleBoxFlat_ufjut") +Button/styles/hover = SubResource("StyleBoxFlat_fcbqo") +Button/styles/normal = SubResource("StyleBoxFlat_t6i7a") +MarginContainer/constants/margin_bottom = 4 +MarginContainer/constants/margin_left = 8 +MarginContainer/constants/margin_right = 8 +MarginContainer/constants/margin_top = 4 +Panel/styles/panel = SubResource("StyleBoxFlat_uy0d5") + +[node name="ExampleBalloon" type="CanvasLayer"] +layer = 100 +script = ExtResource("1_wmucd") + +[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"] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 3.0 +offset_top = -62.0 +offset_right = -4.0 +offset_bottom = -4.0 +grow_horizontal = 2 +grow_vertical = 0 +theme = ExtResource("2_i6ssm") + +[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 +theme = ExtResource("2_i6ssm") + +[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.498039) +layout_mode = 2 +mouse_filter = 1 +bbcode_enabled = true +text = "Character" +fit_content = true +scroll_active = false + +[node name="DialogueLabel" parent="Balloon/Panel/Dialogue/VBoxContainer" instance=ExtResource("3_np1qn")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +text = "Dialogue..." + +[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 = -124.0 +offset_top = -218.0 +offset_right = 125.0 +offset_bottom = -50.0 +grow_horizontal = 2 +grow_vertical = 0 +theme = ExtResource("2_i6ssm") + +[node name="ResponsesMenu" type="VBoxContainer" parent="Balloon/Responses"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 8 +theme_override_constants/separation = 2 +script = ExtResource("4_qcru4") + +[node name="ResponseExample" type="Button" parent="Balloon/Responses/ResponsesMenu"] +layout_mode = 2 +text = "Response Example" + +[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"] diff --git a/assets/equipped-icon.png b/assets/equipped-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b9f726eb34ad332c9d4ccf2a8c8203f2cfc241fd GIT binary patch literal 162 zcmeAS@N?(olHy`uVBq!ia0vp^20$#p!3HD)*8SNCq!^2X+?^QKos)S9<ivQoIEHw1 zzP-GWk3oQkB|!b(|LNI=3a*cM)_&=2R|^T|YHYF;5R^1yxNz;)oTFFHu6EjeX40D0 zjIj2&eRk3QdmGeUx!2aup7)zC=4^v%ec6L2UwaI`-YHjL31WTZs35g*8E-bw9tKZW KKbLh*2~7Y7Ogbb0 literal 0 HcmV?d00001 diff --git a/assets/equipped-icon.png.import b/assets/equipped-icon.png.import new file mode 100644 index 0000000..d0aaae3 --- /dev/null +++ b/assets/equipped-icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c7retsmbiaoy4" +path="res://.godot/imported/equipped-icon.png-e310f1f9d8d71994fb85fb03a818c6b7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/equipped-icon.png" +dest_files=["res://.godot/imported/equipped-icon.png-e310f1f9d8d71994fb85fb03a818c6b7.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 diff --git a/assets/item_icons/x.png b/assets/item_icons/x.png new file mode 100644 index 0000000000000000000000000000000000000000..36598307451b577b14dd7cfd3f257a15bcba5a5d GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|nmt_{Lo9md zPCm_hK!L}3?mOn+?<Y2%S{jmB=XRF&#AX>DhKApoGSl9Q^LKR^+*qf7?ZCMuHU)m0 z<U(6Zc%zpz#j~q_Gp;x%so&EXVPTP=B*!*MBqGwH^nlxkmw$G-XkR+EBV8_eijv85 z+v2Z&hvH8>IG5_Nuxahv^YcRAJvh_3Dv5D+R{hh62!0u$a~M2b{an^LB{Ts5;M7g% literal 0 HcmV?d00001 diff --git a/assets/item_icons/x.png.import b/assets/item_icons/x.png.import new file mode 100644 index 0000000..9bea815 --- /dev/null +++ b/assets/item_icons/x.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bk51v1m1wfhex" +path="res://.godot/imported/x.png-3ec7665c51167d707c62ab68705ebe01.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/item_icons/x.png" +dest_files=["res://.godot/imported/x.png-3ec7665c51167d707c62ab68705ebe01.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 diff --git a/assets/ui_themes/new_theme.tres b/assets/ui_themes/new_theme.tres new file mode 100644 index 0000000..6bc4691 --- /dev/null +++ b/assets/ui_themes/new_theme.tres @@ -0,0 +1,16 @@ +[gd_resource type="Theme" load_steps=3 format=3 uid="uid://eyq5i2mlpkwn"] + +[ext_resource type="FontFile" uid="uid://ddjw625xpmwtc" path="res://assets/Not Jam UI Condensed 16.ttf" id="1_eoag7"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_h7nxl"] +bg_color = Color(0.301961, 0.301961, 0.301961, 1) +border_width_left = 2 +border_width_top = 2 +border_width_right = 2 +border_width_bottom = 2 +border_color = Color(1, 1, 1, 1) + +[resource] +default_font = ExtResource("1_eoag7") +default_font_size = 16 +Panel/styles/panel = SubResource("StyleBoxFlat_h7nxl") diff --git a/project.godot b/project.godot index 0c34852..95c1d12 100644 --- a/project.godot +++ b/project.godot @@ -19,6 +19,11 @@ config/icon="res://icon.svg" DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd" PlayerState="res://src/autoloads/player_state.gd" +ItemDb="*res://src/items/item_db.gd" + +[dialogue_manager] + +general/balloon_path="res://assets/dialogue_boxes/balloon.tscn" [display] @@ -54,11 +59,21 @@ interact={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) ] } -adv_text={ +adv_txt={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null) ] } +cancel_txt={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":88,"key_label":0,"unicode":120,"echo":false,"script":null) +] +} +inventory={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":99,"echo":false,"script":null) +] +} [internationalization] diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd index ed93a91..684b731 100644 --- a/src/autoloads/player_state.gd +++ b/src/autoloads/player_state.gd @@ -3,19 +3,19 @@ extends Node # these are functions that can be called in the dialog system func has_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - return player.has_boots + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + return player.has_boots func _give_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - player.give_boots() - var ui = current_scene.get_node("UI") - ui.bootIcon.visible = true + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + player.give_boots() + var ui = current_scene.get_node("UI") + ui.bootIcon.visible = true # ion know what this returns func _get_current_scene(): - return get_tree().get_root().get_children()[2] \ No newline at end of file + return get_tree().get_root().get_children()[2] diff --git a/src/items/item_db.gd b/src/items/item_db.gd new file mode 100644 index 0000000..4af0963 --- /dev/null +++ b/src/items/item_db.gd @@ -0,0 +1,29 @@ +extends Resource + +#currently auto-loaded, although I think we could get away with it being a static script, as it dosen't have any instanced values we need to maintain, + + +const ITEMS = { + 0:{ + "id_name":"test_item", + "title": "Test Item", + "icon":"x.png", + "description":"You shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden." + }, + 1:{ + "name":"test_item1", + "title": "Another Test Item", + "icon":"x.png", + "description":"You (also) shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden." + } +} + +# item constructor +func give_item(id:int) -> void: + var new_item:Item = Item.new() + new_item.id_name = ITEMS[id]["name"] + new_item.title = ITEMS[id]["title"] + new_item.icon = ITEMS[id]["icon"] + new_item.description = ITEMS[id]["description"] + # add resource to player inventory + diff --git a/src/items/item_res.gd b/src/items/item_res.gd new file mode 100644 index 0000000..10ffba7 --- /dev/null +++ b/src/items/item_res.gd @@ -0,0 +1,14 @@ +class_name Item +extends Resource + +var icon:Texture +var id_name:String +var title:String +var description:String +var in_inventory = false + +func given_to_player(): + in_inventory = true + +func removed_from_player(): + in_inventory = false \ No newline at end of file diff --git a/src/items/test_item.tres b/src/items/test_item.tres new file mode 100644 index 0000000..4e0fa23 --- /dev/null +++ b/src/items/test_item.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="Item" load_steps=2 format=3 uid="uid://c5ru2507ecm8f"] + +[ext_resource type="Script" path="res://src/items/item.gd" id="1_b1mog"] + +[resource] +script = ExtResource("1_b1mog") +id = 0 +ui_name = "" +description = "" diff --git a/src/main/main.tscn b/src/main/main.tscn index de4db7b..cb0cca0 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=8 format=3 uid="uid://cv5xm6ru2dkxf"] +[gd_scene load_steps=10 format=3 uid="uid://cv5xm6ru2dkxf"] [ext_resource type="Script" path="res://src/main/main.gd" id="1_8hq0w"] [ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] @@ -7,9 +7,12 @@ [ext_resource type="Script" path="res://src/main/ui.gd" id="4_o4xue"] [ext_resource type="Texture2D" uid="uid://5kstmna3yb6t" path="res://assets/white.png" id="6_8laen"] [ext_resource type="FontFile" uid="uid://ddjw625xpmwtc" path="res://assets/Not Jam UI Condensed 16.ttf" id="6_sa7lc"] +[ext_resource type="Texture2D" uid="uid://c7retsmbiaoy4" path="res://assets/equipped-icon.png" id="8_h4ayj"] +[ext_resource type="Theme" uid="uid://eyq5i2mlpkwn" path="res://assets/ui_themes/new_theme.tres" id="8_xwmxw"] [node name="Main" type="Node2D"] script = ExtResource("1_8hq0w") +metadata/_edit_vertical_guides_ = [128.0] [node name="Player" parent="." instance=ExtResource("2_ekt33")] position = Vector2(80, 48) @@ -48,14 +51,20 @@ offset_bottom = 16.0 [node name="Bar" type="TextureRect" parent="UI/HUD"] layout_mode = 2 -offset_right = 256.0 +offset_left = 1.0 +offset_right = 257.0 offset_bottom = 17.0 texture = ExtResource("6_8laen") -[node name="BootIcon" type="Sprite2D" parent="UI/HUD"] -visible = false -modulate = Color(0, 0, 0, 1) -position = Vector2(160, 0) +[node name="EquippedWrapper" type="Sprite2D" parent="UI/HUD"] +modulate = Color(0.301961, 0.301961, 0.301961, 1) +position = Vector2(144, 0) +texture = ExtResource("8_h4ayj") +centered = false +region_rect = Rect2(640, 16, 16, 16) + +[node name="EquippedItem" type="Sprite2D" parent="UI/HUD/EquippedWrapper"] +position = Vector2(16, 0) texture = ExtResource("1_kghfi") centered = false region_enabled = true @@ -66,30 +75,69 @@ layout_mode = 2 offset_left = 16.0 offset_right = 54.0 offset_bottom = 16.0 -theme_override_colors/font_color = Color(0, 0, 0, 1) +theme = ExtResource("8_xwmxw") +theme_override_colors/font_color = Color(0.301961, 0.301961, 0.301961, 1) theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "HP: 3/3" -[node name="HPLabel2" type="Label" parent="UI/HUD"] +[node name="Gold Label" type="Label" parent="UI/HUD"] layout_mode = 2 offset_left = 192.0 offset_right = 206.0 offset_bottom = 16.0 -theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_color = Color(0.301961, 0.301961, 0.301961, 1) theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "0g" -[node name="HPLabel3" type="Label" parent="UI/HUD"] +[node name="FloorLabel" type="Label" parent="UI/HUD"] layout_mode = 2 offset_left = 224.0 offset_right = 262.0 offset_bottom = 16.0 -theme_override_colors/font_color = Color(0, 0, 0, 1) +theme = ExtResource("8_xwmxw") +theme_override_colors/font_color = Color(0.301961, 0.301961, 0.301961, 1) theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "B00" -[node name="Player2" parent="." instance=ExtResource("2_ekt33")] -position = Vector2(130, 47) +[node name="CanvasLayer" type="CanvasLayer" parent="."] +visible = false + +[node name="Menu" type="Control" parent="CanvasLayer"] +layout_mode = 3 +anchors_preset = 0 +offset_top = 17.0 +offset_right = 256.0 +offset_bottom = 144.0 + +[node name="Panel" type="Panel" parent="CanvasLayer/Menu"] +layout_mode = 0 +offset_right = 256.0 +offset_bottom = 127.0 +theme = ExtResource("8_xwmxw") + +[node name="VBoxRight" type="VBoxContainer" parent="CanvasLayer/Menu/Panel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = -128.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Panel2" type="Panel" parent="CanvasLayer/Menu"] +layout_mode = 0 +offset_left = 128.0 +offset_right = 256.0 +offset_bottom = 127.0 +theme = ExtResource("8_xwmxw") + +[node name="VBoxLeft" type="VBoxContainer" parent="CanvasLayer/Menu/Panel2"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/src/main/ui.gd b/src/main/ui.gd index a7c02d2..3d7e455 100644 --- a/src/main/ui.gd +++ b/src/main/ui.gd @@ -22,7 +22,7 @@ func render_text(new_text_arr) -> void: textbox.visible = false text_removed.emit() -func _input(event: InputEvent) -> void: - if event.is_action_pressed("adv_text"): - text_advanced.emit() +#func _input(event: InputEvent) -> void: + #if event.is_action_pressed("adv_text"): + #text_advanced.emit() diff --git a/src/player/player.gd b/src/player/player.gd index c744812..d3e5105 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -39,7 +39,7 @@ func _unhandled_input(event: InputEvent) -> void: if _input_dir != Vector2.ZERO: _move(_input_dir) return - if event.is_action_pressed('ui_accept'): + if event.is_action_pressed('interact'): _interact() diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 4cb98a8..e997a08 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -5,6 +5,9 @@ signal inspected @export var dialog_resource: DialogueResource @export var dialog_start: String = "start" +# Should this go into a singleton? +const dialogBox = preload("res://assets/dialogue_boxes/balloon.tscn") + var opened:bool = false @onready var sprite = $Sprite2D @@ -27,7 +30,9 @@ func _on_interaction(player:Player) -> void: return opened = true - DialogueManager.show_example_dialogue_balloon(load("res://src/dialogue/main.dialogue"),"start") + var balloon: Node = dialogBox.instantiate() + get_tree().current_scene.add_child(balloon) + balloon.start(dialog_resource,dialog_start) $Sprite2D.frame = 1 diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..b79f880 --- /dev/null +++ b/todo.md @@ -0,0 +1,17 @@ +# inventory +## inventory datatype: +- manages an Items Id, icon, description(s), and if the player has it or not? (should they manage that too?) +## inventory screen: +- lets you see all the items you currently have with descriptions of them, pressing action button lets you equip it. +## items in game: +- npcs can check your equipped item and special cutscenes can happen + +## format ideas: +### items are all scenes: +- no +### Items are all resources: +- give resources through their url +- would let us manage multiple instances of an item +- maybe the db could act as a master reference, the resource could act as instances? +### item db +- items are all in a big list, give them though id From 2fea0bee2dff21b1a3e7e8c4710e5b5acd4d1f39 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Mon, 15 Apr 2024 19:08:23 -0400 Subject: [PATCH 60/86] item system2 --- src/items/item_db.gd | 6 ++++-- src/player/player.gd | 3 +++ todo.md | 8 ++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/items/item_db.gd b/src/items/item_db.gd index 4af0963..397c12f 100644 --- a/src/items/item_db.gd +++ b/src/items/item_db.gd @@ -8,13 +8,15 @@ const ITEMS = { "id_name":"test_item", "title": "Test Item", "icon":"x.png", - "description":"You shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden." + "description":"You shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden.", + "unique":true, }, 1:{ "name":"test_item1", "title": "Another Test Item", "icon":"x.png", - "description":"You (also) shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden." + "description":"You (also) shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden.", + "unique":true, } } diff --git a/src/player/player.gd b/src/player/player.gd index d3e5105..a412ba7 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -10,6 +10,8 @@ signal moved(dir) const TILE_SIZE := 16 var is_actionable:= true +var inventory := [] + var has_boots := false func _init() -> void: @@ -69,6 +71,7 @@ func _interact() -> void: if interact_tile.is_in_group('interact'): interact_tile._on_interaction(self) + func give_boots(): var boots = boots_packed_scene.instantiate() add_child(boots) diff --git a/todo.md b/todo.md index b79f880..31e904b 100644 --- a/todo.md +++ b/todo.md @@ -15,3 +15,11 @@ - maybe the db could act as a master reference, the resource could act as instances? ### item db - items are all in a big list, give them though id + + +# todo: +- clean up commit tree +- get player (or inventory) ref inside of the item_db class (pull from top down ig) +- add values to player inventory array (should it be a dict?) +- render items to the game when the menu loads +- update currently equipped one \ No newline at end of file From c38e7df657b837fe8c59306569265d984ef30465 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Mon, 15 Apr 2024 19:14:16 -0400 Subject: [PATCH 61/86] shouldn't be pushing directly but now re-has dialogue manager set up --- src/main/ui.gd | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/main/ui.gd b/src/main/ui.gd index 3d7e455..e1a7913 100644 --- a/src/main/ui.gd +++ b/src/main/ui.gd @@ -1,28 +1,8 @@ class_name UI extends Control -@onready var textbox:Panel = $Textbox -@onready var bootIcon:Sprite2D =$HUD/BootIcon -signal text_rendered -signal text_removed -signal text_advanced +#@onready var textbox:Panel = $Textbox +#@onready var bootIcon:Sprite2D =$HUD/BootIcon -func render_text(new_text_arr) -> void: - #loop through the array and display the lines of text - text_rendered.emit() - bootIcon.visible = true - textbox.visible = true - var textLabel = $Textbox/Text - - for line in new_text_arr: - textLabel.text = line - await text_advanced - - textbox.visible = false - text_removed.emit() - -#func _input(event: InputEvent) -> void: - #if event.is_action_pressed("adv_text"): - #text_advanced.emit() From e25b9f4424451e0e9ee04adc68f6812aa8dff5bc Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Mon, 15 Apr 2024 19:42:27 -0400 Subject: [PATCH 62/86] totally gonna push --- src/main/ui.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/ui.gd b/src/main/ui.gd index e1a7913..e8db23f 100644 --- a/src/main/ui.gd +++ b/src/main/ui.gd @@ -3,6 +3,6 @@ extends Control #@onready var textbox:Panel = $Textbox #@onready var bootIcon:Sprite2D =$HUD/BootIcon - +#woah, imma push! From b87fc21094c13740fd1d2742e6b67876e9667371 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Mon, 15 Apr 2024 19:49:35 -0400 Subject: [PATCH 63/86] working off main yipee --- src/autoloads/player_state.gd | 8 ++++---- src/dialogue/main.dialogue | 2 +- src/items/item_db.gd | 2 +- src/main/ui.gd | 24 ------------------------ 4 files changed, 6 insertions(+), 30 deletions(-) diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd index 684b731..a405662 100644 --- a/src/autoloads/player_state.gd +++ b/src/autoloads/player_state.gd @@ -11,11 +11,11 @@ func _give_boots(): var current_scene = _get_current_scene() var player:Player = current_scene.get_node("Player") player.give_boots() - var ui = current_scene.get_node("UI") - ui.bootIcon.visible = true + #var ui = current_scene.get_node("UI") + #ui.bootIcon.visible = true -# ion know what this returns +# this value keeps changing based on the amount of autoloads we have func _get_current_scene(): - return get_tree().get_root().get_children()[2] + return get_tree().get_root().get_children()[3] diff --git a/src/dialogue/main.dialogue b/src/dialogue/main.dialogue index e735370..aadf753 100644 --- a/src/dialogue/main.dialogue +++ b/src/dialogue/main.dialogue @@ -3,7 +3,7 @@ if PlayerState.has_boots() == false The chest contained boots. do PlayerState._give_boots() - They fit you perfectly. (did you see the change in the ui!?!?) + They fit you perfectly. (currently no UI change) An air of unease overwhelms you. Something is wrong... else: diff --git a/src/items/item_db.gd b/src/items/item_db.gd index 397c12f..116d514 100644 --- a/src/items/item_db.gd +++ b/src/items/item_db.gd @@ -1,4 +1,4 @@ -extends Resource +extends Node #currently auto-loaded, although I think we could get away with it being a static script, as it dosen't have any instanced values we need to maintain, diff --git a/src/main/ui.gd b/src/main/ui.gd index 3d7e455..d55645c 100644 --- a/src/main/ui.gd +++ b/src/main/ui.gd @@ -1,28 +1,4 @@ class_name UI extends Control -@onready var textbox:Panel = $Textbox -@onready var bootIcon:Sprite2D =$HUD/BootIcon -signal text_rendered -signal text_removed -signal text_advanced - - -func render_text(new_text_arr) -> void: - #loop through the array and display the lines of text - text_rendered.emit() - bootIcon.visible = true - textbox.visible = true - var textLabel = $Textbox/Text - - for line in new_text_arr: - textLabel.text = line - await text_advanced - - textbox.visible = false - text_removed.emit() - -#func _input(event: InputEvent) -> void: - #if event.is_action_pressed("adv_text"): - #text_advanced.emit() From 93b43c63d2e0c60fdf50bac8232ee3000aa91572 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 16 Mar 2024 17:30:34 -0400 Subject: [PATCH 64/86] send ppl to boot --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 46af03f..33383e9 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # The-Maze-With-GDYU A collaborative experiment between GDYU friends. - CURRENTLY: - - Prototyping all our gameplay mechanics, pick an task from the [Project Board](https://github.com/orgs/GDYUClub/projects/1) if you'd like to help +## Current Goal: Bootstrap Version. +Prototype all of our gameplay mechanics and put them together by MARCH 20TH +To look at what needs to get done, view the [Github Project Page](https://github.com/orgs/GDYUClub/projects/1/views/1) Here's a [video](https://youtu.be/xjZsrdWe2jU) to understand what this is! @@ -10,6 +11,8 @@ Here's the [design doc](https://docs.google.com/document/d/1vs-uuo3EVE-bTyuviN5F Read [contributing.md](/docs/contributing.md) before working on the repository. +Read [contributing.md](/docs/contributing.md) before working on the repository. + DUE MAY 31 2024 23:59 EST ![THEMAZEphoto](/docs/gh_readme_assets/THEMAZEhahahahatestingargstuffifyouseethismessagemesayingyoudidhehehe2.png) From c463d037d430e5f582e7bd4f90a06c50f9f9c8dd Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 16 Mar 2024 17:37:23 -0400 Subject: [PATCH 65/86] writing instructions for the 999th time --- docs/contributing.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/contributing.md b/docs/contributing.md index d5653e6..352f400 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -1,7 +1,6 @@ # How to contribute to The Maze -- Follow a Git workflow of fork -> clone -> branch -> pr -> merge +- Follow a Git workflow of branch -> pr -> merge - If you're new to Git look [here](https://docs.github.com/en/get-started/quickstart/contributing-to-projects) - ## general - Keep file and folder names in `snake_case` (godot 4 standard) From 45d14ded84720b9399a9f8bb4b35df6eb44dce4f Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Mon, 15 Apr 2024 20:42:52 -0400 Subject: [PATCH 66/86] rebasing j --- src/player/player.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/player/player.gd b/src/player/player.gd index a412ba7..7b98d13 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -75,4 +75,4 @@ func _interact() -> void: func give_boots(): var boots = boots_packed_scene.instantiate() add_child(boots) - has_boots = true \ No newline at end of file + has_boots = true From b471734aecdcd6e6459a863993a556904b4fc531 Mon Sep 17 00:00:00 2001 From: Haigsov <haigsouv@my.yorku.ca> Date: Sat, 23 Mar 2024 21:20:53 -0400 Subject: [PATCH 67/86] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f0e8e76..0b4ced5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ .godot/ .vscode/settings.json # don't keep the addons in the repo -addons/ \ No newline at end of file +addons/ From 8a2871baf1b821e71c7e57a1f5ff964593ad75e7 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Fri, 15 Mar 2024 19:33:10 -0400 Subject: [PATCH 68/86] blank project --- project.godot | 1 - 1 file changed, 1 deletion(-) diff --git a/project.godot b/project.godot index 95c1d12..299c5bc 100644 --- a/project.godot +++ b/project.godot @@ -85,6 +85,5 @@ locale/translations_pot_files=PackedStringArray("res://src/dialogue/main.dialogu [rendering] -textures/canvas_textures/default_texture_filter=0 renderer/rendering_method="gl_compatibility" renderer/rendering_method.mobile="gl_compatibility" From f41ee5da49b87ec45a520a93d435cb004c2a0e5d Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sat, 16 Mar 2024 15:28:40 -0400 Subject: [PATCH 69/86] tilemap data structure set up, make as seperate scene --- project.godot | 1 + 1 file changed, 1 insertion(+) diff --git a/project.godot b/project.godot index 299c5bc..95c1d12 100644 --- a/project.godot +++ b/project.godot @@ -85,5 +85,6 @@ locale/translations_pot_files=PackedStringArray("res://src/dialogue/main.dialogu [rendering] +textures/canvas_textures/default_texture_filter=0 renderer/rendering_method="gl_compatibility" renderer/rendering_method.mobile="gl_compatibility" From 6112e817d27b6c6fd37bf8f11a24df47408a2d22 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Mon, 15 Apr 2024 21:23:42 -0400 Subject: [PATCH 70/86] re-added .obsidain to ignore --- .gitignore | 1 + src/main/main.gd | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 0b4ced5..28fdf12 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .vscode/settings.json # don't keep the addons in the repo addons/ +.obsidian/ \ No newline at end of file diff --git a/src/main/main.gd b/src/main/main.gd index 38ff892..5aa4bcb 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -18,8 +18,8 @@ var shuffled_maps:Array = [] var current_map_id func _ready() -> void: - ui.text_rendered.connect(_start_cutscene) - ui.text_removed.connect(_end_cutscene) + #ui.text_rendered.connect(_start_cutscene) + #ui.text_removed.connect(_end_cutscene) player.walked_into_stairs.connect(next_map) pass From e17386315ec9154b0dd99e546c335bef400f7100 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Tue, 16 Apr 2024 21:10:17 -0400 Subject: [PATCH 71/86] items rendering in menu, not using ui nodes --- assets/menu_arrow.png | Bin 0 -> 119 bytes assets/menu_arrow.png.import | 34 ++++++++++++++ project.godot | 2 +- src/autoloads/player_state.gd | 5 +- src/dialogue/main.dialogue | 13 ++---- src/items/item_db.gd | 17 ++++--- src/main/main.gd | 21 +++++---- src/main/main.tscn | 57 +++++++--------------- src/main/menu_layer.gd | 83 +++++++++++++++++++++++++++++++++ src/player/player.gd | 4 ++ src/scene-tiles/chest/chest.gd | 4 +- todo.md | 3 -- 12 files changed, 173 insertions(+), 70 deletions(-) create mode 100644 assets/menu_arrow.png create mode 100644 assets/menu_arrow.png.import create mode 100644 src/main/menu_layer.gd diff --git a/assets/menu_arrow.png b/assets/menu_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..4542eac291f5d0e087b936f12b82eee8fae819bc GIT binary patch literal 119 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqjKx9jP7LeL$-D$|3_V>OLnNm5 z_BnDf81NjL_4ohzcTrB^&wP6_rcP10E6?0ku$Vi6b)N8jh65D^b4x22gRG^$-diJX Q2-M8r>FVdQ&MBb@03qijG5`Po literal 0 HcmV?d00001 diff --git a/assets/menu_arrow.png.import b/assets/menu_arrow.png.import new file mode 100644 index 0000000..2dd3f5c --- /dev/null +++ b/assets/menu_arrow.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bbi13ou2tmyip" +path="res://.godot/imported/menu_arrow.png-2e32d3585e0043243fe1bb1337347455.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/menu_arrow.png" +dest_files=["res://.godot/imported/menu_arrow.png-2e32d3585e0043243fe1bb1337347455.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 diff --git a/project.godot b/project.godot index 95c1d12..fa76950 100644 --- a/project.godot +++ b/project.godot @@ -69,7 +69,7 @@ cancel_txt={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":88,"key_label":0,"unicode":120,"echo":false,"script":null) ] } -inventory={ +menu={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":99,"echo":false,"script":null) ] diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd index 271f4cc..4f46d91 100644 --- a/src/autoloads/player_state.gd +++ b/src/autoloads/player_state.gd @@ -1,6 +1,7 @@ extends Node # these are functions that can be called in the dialog system +# should probably re-name to something more descriptive func has_boots(): var current_scene = _get_current_scene() @@ -10,7 +11,7 @@ func has_boots(): func _give_boots(): var current_scene = _get_current_scene() var player:Player = current_scene.get_node("Player") - player.give_boots() + ItemDb.give_item(0) #var ui = current_scene.get_node("UI") #ui.bootIcon.visible = true @@ -19,5 +20,5 @@ func _give_boots(): # this value keeps changing based on the amount of autoloads we have func _get_current_scene(): - return get_tree().get_root().get_children()[3] + return get_tree().get_root().get_children()[-1] diff --git a/src/dialogue/main.dialogue b/src/dialogue/main.dialogue index 2ad7b75..7b4dec4 100644 --- a/src/dialogue/main.dialogue +++ b/src/dialogue/main.dialogue @@ -1,13 +1,8 @@ ~ start -if PlayerState.has_boots() == false - The chest contained boots. - do PlayerState._give_boots() +#if PlayerState.has_boots() == false +boots? +do PlayerState._give_boots() +#else: - They fit you perfectly. (currently no UI change) - - An air of unease overwhelms you. - Something is wrong... -else: - You already took the boots. Nothing has been added in between then and now. => END \ No newline at end of file diff --git a/src/items/item_db.gd b/src/items/item_db.gd index e1587b0..df53c10 100644 --- a/src/items/item_db.gd +++ b/src/items/item_db.gd @@ -1,20 +1,16 @@ - extends Node #currently auto-loaded, although I think we could get away with it being a static script, as it dosen't have any instanced values we need to maintain, - const ITEMS = { 0:{ - "id_name":"test_item", "title": "Test Item", "icon":"x.png", "description":"You shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden.", "unique":true, }, 1:{ - "name":"test_item1", "title": "Another Test Item", "icon":"x.png", "description":"You (also) shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden.", @@ -25,9 +21,18 @@ const ITEMS = { # item constructor func give_item(id:int) -> void: var new_item:Item = Item.new() - new_item.id_name = ITEMS[id]["name"] new_item.title = ITEMS[id]["title"] - new_item.icon = ITEMS[id]["icon"] + var icon_name = ITEMS[id]["icon"] + new_item.icon = load("res://assets/item_icons/" + icon_name) new_item.description = ITEMS[id]["description"] # add resource to player inventory + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + player.inventory.append(new_item) + print('player now has item: ', new_item) + + +func _get_current_scene(): + return get_tree().get_root().get_children()[3] + diff --git a/src/main/main.gd b/src/main/main.gd index 5aa4bcb..573f124 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -1,9 +1,9 @@ extends Node2D @onready var ui:UI = $UI +@onready var menuLayer = $MenuLayer @onready var player:Player = $Player @onready var current_map:Node2D = $Map - var in_cutscene := false var maps:Array = [preload('res://src/maps/map-1.tscn'),preload('res://src/maps/map-2.tscn'),preload('res://src/maps/map-3.tscn')] @@ -54,12 +54,17 @@ func swap_map() -> void: var playerSpawnMarker:Marker2D = nextMap.get_node('PlayerSpawn') player.position = playerSpawnMarker.position +func _toggle_menu(inventory) -> void: + menuLayer.visible = true + menuLayer._load_items(inventory) + pass -func _start_cutscene() -> void: - in_cutscene = true - player.is_actionable = false +#unused, will remove later +#func _start_cutscene() -> void: + #in_cutscene = true + #player.is_actionable = false -func _end_cutscene() -> void: - in_cutscene = false - await get_tree().create_timer(0.01).timeout # 10ms buffer hack to prevent input collision from text advancing and player input, could also solve by checking UI input in player _input event? - player.is_actionable = true +#func _end_cutscene() -> void: + #in_cutscene = false + #await get_tree().create_timer(0.01).timeout # 10ms buffer hack to prevent input collision from text advancing and player input, could also solve by checking UI input in player _input event? + #player.is_actionable = true diff --git a/src/main/main.tscn b/src/main/main.tscn index cb0cca0..1947a11 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=10 format=3 uid="uid://cv5xm6ru2dkxf"] +[gd_scene load_steps=12 format=3 uid="uid://cv5xm6ru2dkxf"] [ext_resource type="Script" path="res://src/main/main.gd" id="1_8hq0w"] [ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] @@ -9,6 +9,8 @@ [ext_resource type="FontFile" uid="uid://ddjw625xpmwtc" path="res://assets/Not Jam UI Condensed 16.ttf" id="6_sa7lc"] [ext_resource type="Texture2D" uid="uid://c7retsmbiaoy4" path="res://assets/equipped-icon.png" id="8_h4ayj"] [ext_resource type="Theme" uid="uid://eyq5i2mlpkwn" path="res://assets/ui_themes/new_theme.tres" id="8_xwmxw"] +[ext_resource type="Script" path="res://src/main/menu_layer.gd" id="10_4w87j"] +[ext_resource type="Texture2D" uid="uid://bbi13ou2tmyip" path="res://assets/menu_arrow.png" id="11_3qv77"] [node name="Main" type="Node2D"] script = ExtResource("1_8hq0w") @@ -27,23 +29,6 @@ offset_right = 256.0 offset_bottom = 144.0 script = ExtResource("4_o4xue") -[node name="Textbox" type="Panel" parent="UI"] -visible = false -layout_mode = 0 -offset_left = 16.0 -offset_top = 96.0 -offset_right = 240.0 -offset_bottom = 128.0 - -[node name="Text" type="Label" parent="UI/Textbox"] -layout_mode = 0 -offset_right = 224.0 -offset_bottom = 32.0 -theme_override_fonts/font = ExtResource("6_sa7lc") -theme_override_font_sizes/font_size = 16 -text = "I told you to not let Jayden make the ui bruh!!!" -autowrap_mode = 2 - [node name="HUD" type="Control" parent="UI"] anchors_preset = 0 offset_right = 256.0 @@ -94,7 +79,7 @@ text = "0g" [node name="FloorLabel" type="Label" parent="UI/HUD"] layout_mode = 2 offset_left = 224.0 -offset_right = 262.0 +offset_right = 257.0 offset_bottom = 16.0 theme = ExtResource("8_xwmxw") theme_override_colors/font_color = Color(0.301961, 0.301961, 0.301961, 1) @@ -102,42 +87,36 @@ theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "B00" -[node name="CanvasLayer" type="CanvasLayer" parent="."] +[node name="MenuLayer" type="CanvasLayer" parent="."] visible = false +script = ExtResource("10_4w87j") -[node name="Menu" type="Control" parent="CanvasLayer"] +[node name="Menu" type="Control" parent="MenuLayer"] layout_mode = 3 anchors_preset = 0 offset_top = 17.0 offset_right = 256.0 offset_bottom = 144.0 -[node name="Panel" type="Panel" parent="CanvasLayer/Menu"] +[node name="Panel" type="Panel" parent="MenuLayer/Menu"] layout_mode = 0 offset_right = 256.0 offset_bottom = 127.0 theme = ExtResource("8_xwmxw") -[node name="VBoxRight" type="VBoxContainer" parent="CanvasLayer/Menu/Panel"] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_right = -128.0 -grow_horizontal = 2 -grow_vertical = 2 +[node name="ItemSlots" type="Control" parent="MenuLayer/Menu/Panel"] +anchors_preset = 0 +offset_left = 2.0 +offset_top = 2.0 +offset_right = 128.0 +offset_bottom = 124.0 + +[node name="ItemCursor" type="Sprite2D" parent="MenuLayer/Menu/Panel/ItemSlots"] +texture = ExtResource("11_3qv77") -[node name="Panel2" type="Panel" parent="CanvasLayer/Menu"] +[node name="Panel2" type="Panel" parent="MenuLayer/Menu"] layout_mode = 0 offset_left = 128.0 offset_right = 256.0 offset_bottom = 127.0 theme = ExtResource("8_xwmxw") - -[node name="VBoxLeft" type="VBoxContainer" parent="CanvasLayer/Menu/Panel2"] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 diff --git a/src/main/menu_layer.gd b/src/main/menu_layer.gd new file mode 100644 index 0000000..23b505b --- /dev/null +++ b/src/main/menu_layer.gd @@ -0,0 +1,83 @@ +extends CanvasLayer +class_name Menu + +@onready var itemSlots:Control = $Menu/Panel/ItemSlots +@onready var itemPanel:Panel = $Menu/Panel +@onready var itemCursor:Sprite2D = $Menu/Panel/ItemSlots/ItemCursor +var item_cursor_row := 0 +var item_cursor_col := 0 +var player_inventory :Array = [] + +const ROWS = 4 +const COLS = 4 + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + pass # Replace with function body. + + +func get_input_vector(event: InputEvent) -> Vector2: + var dir := Vector2.ZERO + if event.is_action_pressed("ui_up"): + dir.y -= 1 + if event.is_action_pressed("ui_down"): + dir.y += 1 + if event.is_action_pressed("ui_left"): + dir.x -= 1 + if event.is_action_pressed("ui_right"): + dir.x += 1 + return dir + + +func _input(event: InputEvent) -> void: + var _input_dir := get_input_vector(event) + #check what group the next tile is in based on your raycast + if _input_dir != Vector2.ZERO: + return + _move_cursor(_input_dir) + +func _move_cursor(input_dir) -> void: + # move based on the row and column (see that's why I did that!!!) + # mod to wrap around values + if abs(input_dir.x) > 0: + item_cursor_col = (item_cursor_col + (1 * input_dir.x)) % COLS + elif abs(input_dir.y) > 0: + item_cursor_row = (item_cursor_row + (1 * input_dir.y)) % ROWS + + itemCursor.position.x = item_cursor_col * 32 + itemCursor.position.y = item_cursor_row * 32 + prints(input_dir,item_cursor_col,item_cursor_row,itemCursor.position) + + + +func _load_items(new_inventory:Array) -> void: + player_inventory = new_inventory + prints("itempalenasd",itemPanel.global_position) + # make sprite 2ds, pass in the texture + # put them on the grid + var item_sprites :Array[Sprite2D] = [] + var margin_x = 8 + var margin_y = 8 + + for item in player_inventory: + print(item) + var new_sprite := Sprite2D.new() + new_sprite.texture = item.icon + item_sprites.append(new_sprite) + print("item sprites: " ,item_sprites.size()) + + for row in ROWS: + for col in COLS: + if item_sprites.size() > 0: + var item_sprite = item_sprites.pop_front() + print(item_sprite) + itemPanel.add_child(item_sprite) + item_sprite.position.x = (32 * col) + 16 + item_sprite.position.y = (20 * row) + 16 + + #put it at the rightmost value to start + itemCursor.position = Vector2(16,16) + + + + diff --git a/src/player/player.gd b/src/player/player.gd index 20c02f4..dd315c3 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -41,9 +41,13 @@ func _unhandled_input(event: InputEvent) -> void: if _input_dir != Vector2.ZERO: _move(_input_dir) return + if event.is_action_pressed('interact'): _interact() + if event.is_action_pressed('menu'): + # don't try this at home + get_parent()._toggle_menu(inventory) func _move(_input_dir:Vector2) -> void: raycast.target_position = _input_dir * TILE_SIZE diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index e997a08..6f69451 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -26,8 +26,8 @@ func _on_interaction(player:Player) -> void: # we need 404.dialog lol return - if opened: - return + #if opened: + #return opened = true var balloon: Node = dialogBox.instantiate() diff --git a/todo.md b/todo.md index 31e904b..10c184d 100644 --- a/todo.md +++ b/todo.md @@ -18,8 +18,5 @@ # todo: -- clean up commit tree -- get player (or inventory) ref inside of the item_db class (pull from top down ig) -- add values to player inventory array (should it be a dict?) - render items to the game when the menu loads - update currently equipped one \ No newline at end of file From d2bd749d4a4e633ae73504c979ef416251487219 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Wed, 17 Apr 2024 21:41:00 -0400 Subject: [PATCH 72/86] ui with ui nodes --- assets/item_cursor.png | Bin 0 -> 131 bytes assets/item_cursor.png.import | 34 +++++++++ src/main/main.tscn | 39 +---------- src/main/menu_layer.gd | 16 +++-- src/menu/menu_layer.tscn | 125 ++++++++++++++++++++++++++++++++++ todo.md | 3 + 6 files changed, 175 insertions(+), 42 deletions(-) create mode 100644 assets/item_cursor.png create mode 100644 assets/item_cursor.png.import create mode 100644 src/menu/menu_layer.tscn diff --git a/assets/item_cursor.png b/assets/item_cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..f179ac33df30d2b3b2012d407cc415b3859668a7 GIT binary patch literal 131 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VV{wqX6T`Z5GB1G~TTd6q5R2aA zKmY&#uV*tkaN@*?4!t(sgv+O0dfb8-l+TDI#kO)EIJ0mU_sYBn8WOCF8zc;vxY>_6 b#wRf|G$$x9hW~p8vVy_W)z4*}Q$iB}AGatq literal 0 HcmV?d00001 diff --git a/assets/item_cursor.png.import b/assets/item_cursor.png.import new file mode 100644 index 0000000..55cf1bf --- /dev/null +++ b/assets/item_cursor.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d22wn20kyg23l" +path="res://.godot/imported/item_cursor.png-41cfccd8b2c7dd6634b158e25553b35e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/item_cursor.png" +dest_files=["res://.godot/imported/item_cursor.png-41cfccd8b2c7dd6634b158e25553b35e.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 diff --git a/src/main/main.tscn b/src/main/main.tscn index 1947a11..ffc23b2 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=3 uid="uid://cv5xm6ru2dkxf"] +[gd_scene load_steps=11 format=3 uid="uid://cv5xm6ru2dkxf"] [ext_resource type="Script" path="res://src/main/main.gd" id="1_8hq0w"] [ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] @@ -9,8 +9,7 @@ [ext_resource type="FontFile" uid="uid://ddjw625xpmwtc" path="res://assets/Not Jam UI Condensed 16.ttf" id="6_sa7lc"] [ext_resource type="Texture2D" uid="uid://c7retsmbiaoy4" path="res://assets/equipped-icon.png" id="8_h4ayj"] [ext_resource type="Theme" uid="uid://eyq5i2mlpkwn" path="res://assets/ui_themes/new_theme.tres" id="8_xwmxw"] -[ext_resource type="Script" path="res://src/main/menu_layer.gd" id="10_4w87j"] -[ext_resource type="Texture2D" uid="uid://bbi13ou2tmyip" path="res://assets/menu_arrow.png" id="11_3qv77"] +[ext_resource type="PackedScene" uid="uid://cx216evccp36t" path="res://src/menu/menu_layer.tscn" id="10_ynrm5"] [node name="Main" type="Node2D"] script = ExtResource("1_8hq0w") @@ -87,36 +86,4 @@ theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "B00" -[node name="MenuLayer" type="CanvasLayer" parent="."] -visible = false -script = ExtResource("10_4w87j") - -[node name="Menu" type="Control" parent="MenuLayer"] -layout_mode = 3 -anchors_preset = 0 -offset_top = 17.0 -offset_right = 256.0 -offset_bottom = 144.0 - -[node name="Panel" type="Panel" parent="MenuLayer/Menu"] -layout_mode = 0 -offset_right = 256.0 -offset_bottom = 127.0 -theme = ExtResource("8_xwmxw") - -[node name="ItemSlots" type="Control" parent="MenuLayer/Menu/Panel"] -anchors_preset = 0 -offset_left = 2.0 -offset_top = 2.0 -offset_right = 128.0 -offset_bottom = 124.0 - -[node name="ItemCursor" type="Sprite2D" parent="MenuLayer/Menu/Panel/ItemSlots"] -texture = ExtResource("11_3qv77") - -[node name="Panel2" type="Panel" parent="MenuLayer/Menu"] -layout_mode = 0 -offset_left = 128.0 -offset_right = 256.0 -offset_bottom = 127.0 -theme = ExtResource("8_xwmxw") +[node name="MenuLayer" parent="." instance=ExtResource("10_ynrm5")] diff --git a/src/main/menu_layer.gd b/src/main/menu_layer.gd index 23b505b..4cab921 100644 --- a/src/main/menu_layer.gd +++ b/src/main/menu_layer.gd @@ -26,27 +26,31 @@ func get_input_vector(event: InputEvent) -> Vector2: dir.x -= 1 if event.is_action_pressed("ui_right"): dir.x += 1 + print(dir) return dir -func _input(event: InputEvent) -> void: +func _unhandled_input(event: InputEvent) -> void: + if visible: + get_viewport().set_input_as_handled() var _input_dir := get_input_vector(event) - #check what group the next tile is in based on your raycast if _input_dir != Vector2.ZERO: return _move_cursor(_input_dir) func _move_cursor(input_dir) -> void: + prints(input_dir,item_cursor_col,item_cursor_row,itemCursor.position) # move based on the row and column (see that's why I did that!!!) # mod to wrap around values if abs(input_dir.x) > 0: - item_cursor_col = (item_cursor_col + (1 * input_dir.x)) % COLS + #item_cursor_col = (item_cursor_col + (1 * input_dir.x)) % COLS + item_cursor_col = item_cursor_col + (1 * input_dir.x) elif abs(input_dir.y) > 0: - item_cursor_row = (item_cursor_row + (1 * input_dir.y)) % ROWS - + #item_cursor_row = (item_cursor_row + (1 * input_dir.y)) % ROWS + item_cursor_row = item_cursor_row + (1 * input_dir.y) + print(item_cursor_col,item_cursor_row) itemCursor.position.x = item_cursor_col * 32 itemCursor.position.y = item_cursor_row * 32 - prints(input_dir,item_cursor_col,item_cursor_row,itemCursor.position) diff --git a/src/menu/menu_layer.tscn b/src/menu/menu_layer.tscn new file mode 100644 index 0000000..b11a081 --- /dev/null +++ b/src/menu/menu_layer.tscn @@ -0,0 +1,125 @@ +[gd_scene load_steps=5 format=3 uid="uid://cx216evccp36t"] + +[ext_resource type="Script" path="res://src/main/menu_layer.gd" id="1_1jpgf"] +[ext_resource type="Theme" uid="uid://eyq5i2mlpkwn" path="res://assets/ui_themes/new_theme.tres" id="2_aexfy"] +[ext_resource type="Texture2D" uid="uid://d22wn20kyg23l" path="res://assets/item_cursor.png" id="3_8ywvp"] +[ext_resource type="Texture2D" uid="uid://bk51v1m1wfhex" path="res://assets/item_icons/x.png" id="4_m23xu"] + +[node name="MenuLayer" type="CanvasLayer"] +layer = 2 +script = ExtResource("1_1jpgf") + +[node name="Menu" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 0 +offset_top = 17.0 +offset_right = 256.0 +offset_bottom = 144.0 + +[node name="TextPanel" type="Panel" parent="Menu"] +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.59375 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("2_aexfy") +metadata/_edit_use_anchors_ = true + +[node name="MarginContainer" type="MarginContainer" parent="Menu/TextPanel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 8 +theme_override_constants/margin_top = 8 +theme_override_constants/margin_right = 8 +theme_override_constants/margin_bottom = 8 + +[node name="Label" type="Label" parent="Menu/TextPanel/MarginContainer"] +layout_mode = 2 +size_flags_vertical = 0 +text = "An important wedding gift." +autowrap_mode = 1 + +[node name="ItemPanel" type="Panel" parent="Menu"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = -102.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("2_aexfy") + +[node name="ItemCursor" type="TextureRect" parent="Menu/ItemPanel"] +layout_mode = 2 +offset_left = 14.0 +offset_top = 14.0 +offset_right = 34.0 +offset_bottom = 34.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +texture = ExtResource("3_8ywvp") +stretch_mode = 2 + +[node name="MarginContainer" type="MarginContainer" parent="Menu/ItemPanel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 16 +theme_override_constants/margin_top = 16 +theme_override_constants/margin_right = 16 +theme_override_constants/margin_bottom = 16 + +[node name="ItemGrid" type="GridContainer" parent="Menu/ItemPanel/MarginContainer"] +layout_mode = 2 +theme_override_constants/h_separation = 8 +theme_override_constants/v_separation = 8 +columns = 5 + +[node name="TextureRect" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] +layout_mode = 2 +texture = ExtResource("4_m23xu") + +[node name="TextureRect2" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] +layout_mode = 2 +texture = ExtResource("4_m23xu") + +[node name="TextureRect3" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] +layout_mode = 2 +texture = ExtResource("4_m23xu") + +[node name="TextureRect4" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] +layout_mode = 2 +texture = ExtResource("4_m23xu") + +[node name="TextureRect5" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] +layout_mode = 2 +texture = ExtResource("4_m23xu") + +[node name="TextureRect6" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] +layout_mode = 2 +texture = ExtResource("4_m23xu") + +[node name="TextureRect7" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] +layout_mode = 2 +texture = ExtResource("4_m23xu") + +[node name="TextureRect8" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] +layout_mode = 2 +texture = ExtResource("4_m23xu") + +[node name="TextureRect9" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] +layout_mode = 2 +texture = ExtResource("4_m23xu") + +[node name="TextureRect10" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] +layout_mode = 2 +texture = ExtResource("4_m23xu") diff --git a/todo.md b/todo.md index 10c184d..92ff736 100644 --- a/todo.md +++ b/todo.md @@ -18,5 +18,8 @@ # todo: +- use grid nodes +- change db to use names instead of numbers - render items to the game when the menu loads +- fix input issues with canvas layer - update currently equipped one \ No newline at end of file From 1804444333eb67fbd0e0a91e35b22e3410cc27ca Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Thu, 18 Apr 2024 20:11:48 -0400 Subject: [PATCH 73/86] item scenes are being instanced, get cursor movement working --- assets/item_cursor.png | Bin 131 -> 131 bytes src/autoloads/player_state.gd | 2 +- src/items/item_db.gd | 13 +++--- src/items/item_res.gd | 2 +- src/main/main.tscn | 1 + src/main/menu_layer.gd | 76 ++++++++++++++-------------------- src/menu/item_ui.gd | 7 ++++ src/menu/item_ui.tscn | 8 ++++ src/menu/menu_layer.tscn | 57 ++++--------------------- src/player/player.gd | 3 ++ 10 files changed, 69 insertions(+), 100 deletions(-) create mode 100644 src/menu/item_ui.gd create mode 100644 src/menu/item_ui.tscn diff --git a/assets/item_cursor.png b/assets/item_cursor.png index f179ac33df30d2b3b2012d407cc415b3859668a7..724fd4760565fb36e460705e594aa5a4b99d9475 100644 GIT binary patch delta 117 zcmZo>Y-UvK4DfU3<&xrJU|`_&^l%9R(gGmN!3HGdKmSjhs3`9J_Oc@vg93-kMf<z| z&s|ni=3vSe-}iLEBPZ5`+dPww91Ppd7P;+i-t5Dl8-f_@EK-kZ8GGz2W_OQ~|GjtX R32vZC44$rjF6*2UngG=<Cu0Br delta 117 zcmZo>Y-UvK4DfU3<&xrJU|`_&^l%9R(jp+t!3HFIJ7sw%DvEn2|M~y_e?6PYffFZA zbm+D5CR{%4(&HAypnOIwDYljSz?p@+xL4*q(2!tV+#q4V#La%pF+Pczp*cZ;G5p^% Pka-NAu6{1-oD!M<s@f!e diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd index 4f46d91..c0ef6c9 100644 --- a/src/autoloads/player_state.gd +++ b/src/autoloads/player_state.gd @@ -11,7 +11,7 @@ func has_boots(): func _give_boots(): var current_scene = _get_current_scene() var player:Player = current_scene.get_node("Player") - ItemDb.give_item(0) + ItemDb.give_item("test0") #var ui = current_scene.get_node("UI") #ui.bootIcon.visible = true diff --git a/src/items/item_db.gd b/src/items/item_db.gd index df53c10..a04c2e2 100644 --- a/src/items/item_db.gd +++ b/src/items/item_db.gd @@ -4,14 +4,14 @@ extends Node #currently auto-loaded, although I think we could get away with it being a static script, as it dosen't have any instanced values we need to maintain, const ITEMS = { - 0:{ + "test0":{ "title": "Test Item", "icon":"x.png", "description":"You shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden.", "unique":true, }, - 1:{ - "title": "Another Test Item", + "test1":{ + "title":"Another Test Item", "icon":"x.png", "description":"You (also) shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden.", "unique":true, @@ -19,20 +19,23 @@ const ITEMS = { } # item constructor -func give_item(id:int) -> void: +func give_item(id:String) -> void: var new_item:Item = Item.new() + new_item.id = id new_item.title = ITEMS[id]["title"] var icon_name = ITEMS[id]["icon"] new_item.icon = load("res://assets/item_icons/" + icon_name) new_item.description = ITEMS[id]["description"] + # add resource to player inventory var current_scene = _get_current_scene() var player:Player = current_scene.get_node("Player") + #if player.has_item(new_item) == false or new_item["unique"] == false: player.inventory.append(new_item) print('player now has item: ', new_item) func _get_current_scene(): - return get_tree().get_root().get_children()[3] + return get_tree().get_root().get_children()[-1] diff --git a/src/items/item_res.gd b/src/items/item_res.gd index 10ffba7..1c7d70e 100644 --- a/src/items/item_res.gd +++ b/src/items/item_res.gd @@ -2,7 +2,7 @@ class_name Item extends Resource var icon:Texture -var id_name:String +var id:String var title:String var description:String var in_inventory = false diff --git a/src/main/main.tscn b/src/main/main.tscn index ffc23b2..02431a3 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -87,3 +87,4 @@ theme_override_font_sizes/font_size = 16 text = "B00" [node name="MenuLayer" parent="." instance=ExtResource("10_ynrm5")] +visible = false diff --git a/src/main/menu_layer.gd b/src/main/menu_layer.gd index 4cab921..36de047 100644 --- a/src/main/menu_layer.gd +++ b/src/main/menu_layer.gd @@ -1,18 +1,19 @@ extends CanvasLayer class_name Menu -@onready var itemSlots:Control = $Menu/Panel/ItemSlots -@onready var itemPanel:Panel = $Menu/Panel -@onready var itemCursor:Sprite2D = $Menu/Panel/ItemSlots/ItemCursor -var item_cursor_row := 0 -var item_cursor_col := 0 -var player_inventory :Array = [] +@onready var itemGrid:GridContainer = %ItemGrid +@onready var itemCursor:TextureRect = %ItemCursor +var cursor_pos:= Vector2i(0,0) + +var item_icon_scene:PackedScene = preload("res://src/menu/item_ui.tscn") -const ROWS = 4 -const COLS = 4 +var player_inventory :Array = [] +# y = rows x = columns +var item_grid_bounds:= Vector2i(0,0) # Called when the node enters the scene tree for the first time. func _ready() -> void: + pass # Replace with function body. @@ -26,7 +27,6 @@ func get_input_vector(event: InputEvent) -> Vector2: dir.x -= 1 if event.is_action_pressed("ui_right"): dir.x += 1 - print(dir) return dir @@ -39,48 +39,36 @@ func _unhandled_input(event: InputEvent) -> void: _move_cursor(_input_dir) func _move_cursor(input_dir) -> void: - prints(input_dir,item_cursor_col,item_cursor_row,itemCursor.position) - # move based on the row and column (see that's why I did that!!!) - # mod to wrap around values + print(input_dir) + #cursor is 16 + 16 * pos + #offset is pos - 1 * 8 if abs(input_dir.x) > 0: - #item_cursor_col = (item_cursor_col + (1 * input_dir.x)) % COLS - item_cursor_col = item_cursor_col + (1 * input_dir.x) - elif abs(input_dir.y) > 0: - #item_cursor_row = (item_cursor_row + (1 * input_dir.y)) % ROWS - item_cursor_row = item_cursor_row + (1 * input_dir.y) - print(item_cursor_col,item_cursor_row) - itemCursor.position.x = item_cursor_col * 32 - itemCursor.position.y = item_cursor_row * 32 + cursor_pos.x = wrapi(cursor_pos.x + input_dir.x,0,item_grid_bounds.x) + if abs(input_dir.y) > 0: + cursor_pos.y = wrapi(cursor_pos.y + input_dir.y,0,item_grid_bounds.y) + print("new cursor pos:", cursor_pos) + + + pass func _load_items(new_inventory:Array) -> void: player_inventory = new_inventory - prints("itempalenasd",itemPanel.global_position) - # make sprite 2ds, pass in the texture - # put them on the grid - var item_sprites :Array[Sprite2D] = [] - var margin_x = 8 - var margin_y = 8 - for item in player_inventory: - print(item) - var new_sprite := Sprite2D.new() - new_sprite.texture = item.icon - item_sprites.append(new_sprite) - print("item sprites: " ,item_sprites.size()) - - for row in ROWS: - for col in COLS: - if item_sprites.size() > 0: - var item_sprite = item_sprites.pop_front() - print(item_sprite) - itemPanel.add_child(item_sprite) - item_sprite.position.x = (32 * col) + 16 - item_sprite.position.y = (20 * row) + 16 - - #put it at the rightmost value to start - itemCursor.position = Vector2(16,16) + var new_item_icon := item_icon_scene.instantiate() + # we just store the id of the item in the icon, not the entire resource + new_item_icon.id = item.id + itemGrid.add_child(new_item_icon) + item_grid_bounds.x = itemGrid.columns + # math to find row count based on number of children + item_grid_bounds.y = ceili(float(itemGrid.get_child_count())/float(itemGrid.columns)) + print(item_grid_bounds) + + + + + diff --git a/src/menu/item_ui.gd b/src/menu/item_ui.gd new file mode 100644 index 0000000..6db4878 --- /dev/null +++ b/src/menu/item_ui.gd @@ -0,0 +1,7 @@ +extends TextureRect +class_name ItemIcon +# is their a simpler way then this? +var id:String + + + diff --git a/src/menu/item_ui.tscn b/src/menu/item_ui.tscn new file mode 100644 index 0000000..72db49b --- /dev/null +++ b/src/menu/item_ui.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=3 format=3 uid="uid://dhi5ko8td6k8x"] + +[ext_resource type="Texture2D" uid="uid://bk51v1m1wfhex" path="res://assets/item_icons/x.png" id="1_poc1b"] +[ext_resource type="Script" path="res://src/menu/item_ui.gd" id="2_02iya"] + +[node name="TextureRect" type="TextureRect"] +texture = ExtResource("1_poc1b") +script = ExtResource("2_02iya") diff --git a/src/menu/menu_layer.tscn b/src/menu/menu_layer.tscn index b11a081..b173583 100644 --- a/src/menu/menu_layer.tscn +++ b/src/menu/menu_layer.tscn @@ -1,9 +1,8 @@ -[gd_scene load_steps=5 format=3 uid="uid://cx216evccp36t"] +[gd_scene load_steps=4 format=3 uid="uid://cx216evccp36t"] [ext_resource type="Script" path="res://src/main/menu_layer.gd" id="1_1jpgf"] [ext_resource type="Theme" uid="uid://eyq5i2mlpkwn" path="res://assets/ui_themes/new_theme.tres" id="2_aexfy"] [ext_resource type="Texture2D" uid="uid://d22wn20kyg23l" path="res://assets/item_cursor.png" id="3_8ywvp"] -[ext_resource type="Texture2D" uid="uid://bk51v1m1wfhex" path="res://assets/item_icons/x.png" id="4_m23xu"] [node name="MenuLayer" type="CanvasLayer"] layer = 2 @@ -39,11 +38,11 @@ theme_override_constants/margin_top = 8 theme_override_constants/margin_right = 8 theme_override_constants/margin_bottom = 8 -[node name="Label" type="Label" parent="Menu/TextPanel/MarginContainer"] +[node name="ItemLabel" type="Label" parent="Menu/TextPanel/MarginContainer"] layout_mode = 2 size_flags_vertical = 0 -text = "An important wedding gift." -autowrap_mode = 1 +text = "Same thing happend to my buddy eric." +autowrap_mode = 2 [node name="ItemPanel" type="Panel" parent="Menu"] layout_mode = 1 @@ -56,11 +55,10 @@ grow_vertical = 2 theme = ExtResource("2_aexfy") [node name="ItemCursor" type="TextureRect" parent="Menu/ItemPanel"] +unique_name_in_owner = true layout_mode = 2 -offset_left = 14.0 -offset_top = 14.0 -offset_right = 34.0 -offset_bottom = 34.0 +offset_right = 16.0 +offset_bottom = 16.0 size_flags_horizontal = 0 size_flags_vertical = 0 texture = ExtResource("3_8ywvp") @@ -79,47 +77,8 @@ theme_override_constants/margin_right = 16 theme_override_constants/margin_bottom = 16 [node name="ItemGrid" type="GridContainer" parent="Menu/ItemPanel/MarginContainer"] +unique_name_in_owner = true layout_mode = 2 theme_override_constants/h_separation = 8 theme_override_constants/v_separation = 8 columns = 5 - -[node name="TextureRect" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] -layout_mode = 2 -texture = ExtResource("4_m23xu") - -[node name="TextureRect2" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] -layout_mode = 2 -texture = ExtResource("4_m23xu") - -[node name="TextureRect3" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] -layout_mode = 2 -texture = ExtResource("4_m23xu") - -[node name="TextureRect4" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] -layout_mode = 2 -texture = ExtResource("4_m23xu") - -[node name="TextureRect5" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] -layout_mode = 2 -texture = ExtResource("4_m23xu") - -[node name="TextureRect6" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] -layout_mode = 2 -texture = ExtResource("4_m23xu") - -[node name="TextureRect7" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] -layout_mode = 2 -texture = ExtResource("4_m23xu") - -[node name="TextureRect8" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] -layout_mode = 2 -texture = ExtResource("4_m23xu") - -[node name="TextureRect9" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] -layout_mode = 2 -texture = ExtResource("4_m23xu") - -[node name="TextureRect10" type="TextureRect" parent="Menu/ItemPanel/MarginContainer/ItemGrid"] -layout_mode = 2 -texture = ExtResource("4_m23xu") diff --git a/src/player/player.gd b/src/player/player.gd index dd315c3..b9875f4 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -82,3 +82,6 @@ func give_boots(): has_boots = true +# we'd need to filter the array for id's, later problem +#func has_item(id:String) -> bool: + #return inventory.has() From 5bbd2280171d55c49e554429968c68739ddbfc61 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Thu, 18 Apr 2024 21:34:26 -0400 Subject: [PATCH 74/86] menu stuff is working --- assets/item_cursor.png | Bin 131 -> 137 bytes assets/item_icons/boots.png | Bin 0 -> 168 bytes assets/item_icons/boots.png.import | 34 ++++++++++++++++++ assets/item_icons/pendant.png | Bin 0 -> 138 bytes assets/item_icons/pendant.png.import | 34 ++++++++++++++++++ assets/item_icons/sword.png | Bin 0 -> 154 bytes assets/item_icons/sword.png.import | 34 ++++++++++++++++++ src/autoloads/player_state.gd | 1 + src/items/item_db.gd | 12 +++---- src/main/main.gd | 1 - src/main/main.tscn | 43 ++++++++++------------- src/main/menu_layer.gd | 50 +++++++++++++++++++-------- src/menu/menu_layer.tscn | 13 ++++++- src/player/player.gd | 2 ++ src/scene-tiles/chest/chest.gd | 1 - 15 files changed, 177 insertions(+), 48 deletions(-) create mode 100644 assets/item_icons/boots.png create mode 100644 assets/item_icons/boots.png.import create mode 100644 assets/item_icons/pendant.png create mode 100644 assets/item_icons/pendant.png.import create mode 100644 assets/item_icons/sword.png create mode 100644 assets/item_icons/sword.png.import diff --git a/assets/item_cursor.png b/assets/item_cursor.png index 724fd4760565fb36e460705e594aa5a4b99d9475..a78784f71b55b8334adf7f9685d53febcfd97e6c 100644 GIT binary patch delta 95 zcmZo>>|~r^7~$;c;uvDloBZeh|Nr%DDhE!SIPn9>{BIyNT|y>-V*<lJAZLDO%vl46 xjf_*6y$&Zlh&7Pv2q`#tKs~kRjb~OF8^hr;|GVcFFim3s0#8>zmvv4FO#rhME5-l- delta 89 zcmV-f0H*(m0fPaMF;YEAL_t(IjqTGx3IHGoMA1Lp|IX7UBM1U(7ry17;z9*r+YFM# v!B)ElS+?D7o5S;fQUE?UWyLBpNWOCiM_eEKy|u^-00000NkvXXu0mjfRoWx& diff --git a/assets/item_icons/boots.png b/assets/item_icons/boots.png new file mode 100644 index 0000000000000000000000000000000000000000..cdaddbb7000e604de48927f6383cc7f0bbe898e3 GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|l001;Lo9mF z208K_P~gx`dG&w(YPmZnTO|%`Je-t&>Dm^S2O3wdx#!lp{5UPd<Z!a{Ni=i)>8eZY zYAN~o>?t#!F_p_?H+fiHJEN)|rCrfE@1RUprpoeJ_d^OxcN_P;`gfSOYD<~voQ~NW QfwnPty85}Sb4q9e0R8el=l}o! literal 0 HcmV?d00001 diff --git a/assets/item_icons/boots.png.import b/assets/item_icons/boots.png.import new file mode 100644 index 0000000..40a0ceb --- /dev/null +++ b/assets/item_icons/boots.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://x2oes4p8o3os" +path="res://.godot/imported/boots.png-7c19fb19d30d36bfa98ea720377bdb18.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/item_icons/boots.png" +dest_files=["res://.godot/imported/boots.png-7c19fb19d30d36bfa98ea720377bdb18.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 diff --git a/assets/item_icons/pendant.png b/assets/item_icons/pendant.png new file mode 100644 index 0000000000000000000000000000000000000000..1b5dbec1f21b9661adfa37746a520495e0cf1db1 GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Ts&PILo9le z6C^%02u?q8K7Rjy<<B>7Mij0(dZA;T<a~>`XwM+$p0u2-nH^VMHl0jay--7-@TSWo kx1ijmbxulGS(*76*iyqf_eskh0Gh|(>FVdQ&MBb@05$V2ng9R* literal 0 HcmV?d00001 diff --git a/assets/item_icons/pendant.png.import b/assets/item_icons/pendant.png.import new file mode 100644 index 0000000..d410c74 --- /dev/null +++ b/assets/item_icons/pendant.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bdr8qxety08dy" +path="res://.godot/imported/pendant.png-27d2e554d13f262262f4094d104cb1df.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/item_icons/pendant.png" +dest_files=["res://.godot/imported/pendant.png-27d2e554d13f262262f4094d104cb1df.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 diff --git a/assets/item_icons/sword.png b/assets/item_icons/sword.png new file mode 100644 index 0000000000000000000000000000000000000000..bc8ddb2805be10dd0badb111203d519f6d123076 GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|LOfj@Lo9le z6BY;<Oj`Bu`TG0+6LZSU!rat~Ob;_$WIJH8dGp3eZ?f9v@2~scF4=HKE^k(0rozdz zlA|it(zD;HWUF0Gt61dVzeq(@CdN<A`ojw@25sA=rdMBT{s)@R;OXk;vd$@?2>^y8 BHmU#s literal 0 HcmV?d00001 diff --git a/assets/item_icons/sword.png.import b/assets/item_icons/sword.png.import new file mode 100644 index 0000000..3e68af9 --- /dev/null +++ b/assets/item_icons/sword.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b5h34yhq75smx" +path="res://.godot/imported/sword.png-9dd1ec7340b1c6849e0082268fce5ce7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/item_icons/sword.png" +dest_files=["res://.godot/imported/sword.png-9dd1ec7340b1c6849e0082268fce5ce7.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 diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd index c0ef6c9..8e863ac 100644 --- a/src/autoloads/player_state.gd +++ b/src/autoloads/player_state.gd @@ -12,6 +12,7 @@ func _give_boots(): var current_scene = _get_current_scene() var player:Player = current_scene.get_node("Player") ItemDb.give_item("test0") + ItemDb.give_item("test1") #var ui = current_scene.get_node("UI") #ui.bootIcon.visible = true diff --git a/src/items/item_db.gd b/src/items/item_db.gd index a04c2e2..8e84233 100644 --- a/src/items/item_db.gd +++ b/src/items/item_db.gd @@ -5,15 +5,15 @@ extends Node const ITEMS = { "test0":{ - "title": "Test Item", - "icon":"x.png", - "description":"You shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden.", + "title": "TEST ITEM", + "icon":"sword.png", + "description":"You shouldn't have this item.", "unique":true, }, "test1":{ - "title":"Another Test Item", - "icon":"x.png", - "description":"You (also) shouldn't have this item. If you do, Jayden made a mistake. Yes, there are other devs on this project, but blame all errors on Jayden.", + "title":"TEST ITEM 2", + "icon":"pendant.png", + "description":"You (also) shouldn't have this item.", "unique":true, } } diff --git a/src/main/main.gd b/src/main/main.gd index 573f124..54d4068 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -1,6 +1,5 @@ extends Node2D -@onready var ui:UI = $UI @onready var menuLayer = $MenuLayer @onready var player:Player = $Player @onready var current_map:Node2D = $Map diff --git a/src/main/main.tscn b/src/main/main.tscn index 02431a3..3b9aa8d 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -1,11 +1,10 @@ -[gd_scene load_steps=11 format=3 uid="uid://cv5xm6ru2dkxf"] +[gd_scene load_steps=10 format=3 uid="uid://cv5xm6ru2dkxf"] [ext_resource type="Script" path="res://src/main/main.gd" id="1_8hq0w"] -[ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_kghfi"] [ext_resource type="PackedScene" uid="uid://bp6oyjqvoyffq" path="res://src/player/player.tscn" id="2_ekt33"] [ext_resource type="PackedScene" uid="uid://deqm4to4ptnq0" path="res://src/maps/map-1.tscn" id="3_w444g"] -[ext_resource type="Script" path="res://src/main/ui.gd" id="4_o4xue"] [ext_resource type="Texture2D" uid="uid://5kstmna3yb6t" path="res://assets/white.png" id="6_8laen"] +[ext_resource type="Texture2D" uid="uid://x2oes4p8o3os" path="res://assets/item_icons/boots.png" id="6_qs3pd"] [ext_resource type="FontFile" uid="uid://ddjw625xpmwtc" path="res://assets/Not Jam UI Condensed 16.ttf" id="6_sa7lc"] [ext_resource type="Texture2D" uid="uid://c7retsmbiaoy4" path="res://assets/equipped-icon.png" id="8_h4ayj"] [ext_resource type="Theme" uid="uid://eyq5i2mlpkwn" path="res://assets/ui_themes/new_theme.tres" id="8_xwmxw"] @@ -20,41 +19,35 @@ position = Vector2(80, 48) [node name="Map" parent="." instance=ExtResource("3_w444g")] -[node name="UI" type="Control" parent="."] -top_level = true +[node name="HUD" type="Control" parent="."] layout_mode = 3 anchors_preset = 0 offset_right = 256.0 -offset_bottom = 144.0 -script = ExtResource("4_o4xue") - -[node name="HUD" type="Control" parent="UI"] -anchors_preset = 0 -offset_right = 256.0 offset_bottom = 16.0 -[node name="Bar" type="TextureRect" parent="UI/HUD"] +[node name="Bar" type="TextureRect" parent="HUD"] layout_mode = 2 offset_left = 1.0 offset_right = 257.0 offset_bottom = 17.0 texture = ExtResource("6_8laen") -[node name="EquippedWrapper" type="Sprite2D" parent="UI/HUD"] +[node name="EquippedWrapper" type="TextureRect" parent="HUD"] modulate = Color(0.301961, 0.301961, 0.301961, 1) -position = Vector2(144, 0) +layout_mode = 0 +offset_left = 144.0 +offset_right = 144.0 texture = ExtResource("8_h4ayj") -centered = false -region_rect = Rect2(640, 16, 16, 16) -[node name="EquippedItem" type="Sprite2D" parent="UI/HUD/EquippedWrapper"] -position = Vector2(16, 0) -texture = ExtResource("1_kghfi") -centered = false -region_enabled = true -region_rect = Rect2(640, 16, 16, 16) +[node name="EquippedItem" type="TextureRect" parent="HUD"] +modulate = Color(0.301961, 0.301961, 0.301961, 1) +layout_mode = 0 +offset_left = 160.0 +offset_right = 176.0 +offset_bottom = 16.0 +texture = ExtResource("6_qs3pd") -[node name="HPLabel" type="Label" parent="UI/HUD"] +[node name="HPLabel" type="Label" parent="HUD"] layout_mode = 2 offset_left = 16.0 offset_right = 54.0 @@ -65,7 +58,7 @@ theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "HP: 3/3" -[node name="Gold Label" type="Label" parent="UI/HUD"] +[node name="Gold Label" type="Label" parent="HUD"] layout_mode = 2 offset_left = 192.0 offset_right = 206.0 @@ -75,7 +68,7 @@ theme_override_fonts/font = ExtResource("6_sa7lc") theme_override_font_sizes/font_size = 16 text = "0g" -[node name="FloorLabel" type="Label" parent="UI/HUD"] +[node name="FloorLabel" type="Label" parent="HUD"] layout_mode = 2 offset_left = 224.0 offset_right = 257.0 diff --git a/src/main/menu_layer.gd b/src/main/menu_layer.gd index 36de047..1aea3a0 100644 --- a/src/main/menu_layer.gd +++ b/src/main/menu_layer.gd @@ -1,8 +1,15 @@ extends CanvasLayer class_name Menu + +@onready var itemDesc:Label = %ItemDesc +@onready var itemTitle:Label = %ItemTitle @onready var itemGrid:GridContainer = %ItemGrid @onready var itemCursor:TextureRect = %ItemCursor + +@onready var player:Player = get_parent().get_node("Player") +@onready var equippedIcon:TextureRect = get_parent().get_node("HUD/EquippedItem") + var cursor_pos:= Vector2i(0,0) var item_icon_scene:PackedScene = preload("res://src/menu/item_ui.tscn") @@ -11,10 +18,14 @@ var player_inventory :Array = [] # y = rows x = columns var item_grid_bounds:= Vector2i(0,0) -# Called when the node enters the scene tree for the first time. -func _ready() -> void: - - pass # Replace with function body. +func equip_item(): + var current_item_index = cursor_pos.x + (cursor_pos.y * item_grid_bounds.x) + print("pulled child: ",current_item_index) + var current_item = itemGrid.get_child(current_item_index) + player.equipped_item = current_item + equippedIcon.texture = load("res://assets/item_icons/" +ItemDb.ITEMS[current_item.id]['icon']) + itemTitle.text = ItemDb.ITEMS[current_item.id]['title'] + itemDesc.text = ItemDb.ITEMS[current_item.id]['description'] func get_input_vector(event: InputEvent) -> Vector2: @@ -30,40 +41,51 @@ func get_input_vector(event: InputEvent) -> Vector2: return dir -func _unhandled_input(event: InputEvent) -> void: +func _input(event: InputEvent) -> void: if visible: get_viewport().set_input_as_handled() - var _input_dir := get_input_vector(event) - if _input_dir != Vector2.ZERO: - return - _move_cursor(_input_dir) + var _input_dir := get_input_vector(event) + if event.is_action_pressed("ui_accept"): + equip_item() + if event.is_action_pressed("menu"): + visible = false + + if _input_dir != Vector2.ZERO: + _move_cursor(_input_dir) func _move_cursor(input_dir) -> void: - print(input_dir) #cursor is 16 + 16 * pos #offset is pos - 1 * 8 if abs(input_dir.x) > 0: cursor_pos.x = wrapi(cursor_pos.x + input_dir.x,0,item_grid_bounds.x) if abs(input_dir.y) > 0: cursor_pos.y = wrapi(cursor_pos.y + input_dir.y,0,item_grid_bounds.y) - print("new cursor pos:", cursor_pos) + itemCursor.position.x = ((16 + 8) * cursor_pos.x) + 16 + itemCursor.position.y = ((16 + 8) * cursor_pos.y) + 16 + + var current_item_index = cursor_pos.x + (cursor_pos.y * item_grid_bounds.x) + var current_item = itemGrid.get_child(current_item_index) + itemTitle.text = ItemDb.ITEMS[current_item.id]['title'] + itemDesc.text = ItemDb.ITEMS[current_item.id]['description'] - pass func _load_items(new_inventory:Array) -> void: + for child in itemGrid.get_children(): + child.queue_free() player_inventory = new_inventory for item in player_inventory: - var new_item_icon := item_icon_scene.instantiate() + var new_item_icon :TextureRect= item_icon_scene.instantiate() # we just store the id of the item in the icon, not the entire resource new_item_icon.id = item.id + new_item_icon.texture = load("res://assets/item_icons/" +ItemDb.ITEMS[item.id]['icon']) itemGrid.add_child(new_item_icon) item_grid_bounds.x = itemGrid.columns # math to find row count based on number of children item_grid_bounds.y = ceili(float(itemGrid.get_child_count())/float(itemGrid.columns)) - print(item_grid_bounds) + print("item grid bounds: ", item_grid_bounds) diff --git a/src/menu/menu_layer.tscn b/src/menu/menu_layer.tscn index b173583..b149a01 100644 --- a/src/menu/menu_layer.tscn +++ b/src/menu/menu_layer.tscn @@ -38,7 +38,18 @@ theme_override_constants/margin_top = 8 theme_override_constants/margin_right = 8 theme_override_constants/margin_bottom = 8 -[node name="ItemLabel" type="Label" parent="Menu/TextPanel/MarginContainer"] +[node name="VBoxContainer" type="VBoxContainer" parent="Menu/TextPanel/MarginContainer"] +layout_mode = 2 + +[node name="ItemTitle" type="Label" parent="Menu/TextPanel/MarginContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 0 +text = "adfasdfasdf" +autowrap_mode = 2 + +[node name="ItemDesc" type="Label" parent="Menu/TextPanel/MarginContainer/VBoxContainer"] +unique_name_in_owner = true layout_mode = 2 size_flags_vertical = 0 text = "Same thing happend to my buddy eric." diff --git a/src/player/player.gd b/src/player/player.gd index b9875f4..0b9eb24 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -14,6 +14,8 @@ var inventory := [] var has_boots := false +var equipped_item:Item + func _init() -> void: add_to_group("player") diff --git a/src/scene-tiles/chest/chest.gd b/src/scene-tiles/chest/chest.gd index 6f69451..4c992ed 100644 --- a/src/scene-tiles/chest/chest.gd +++ b/src/scene-tiles/chest/chest.gd @@ -12,7 +12,6 @@ var opened:bool = false @onready var sprite = $Sprite2D #bad solution but not a bad solution YET -@onready var ui:UI = get_parent().get_parent().get_node('UI') func _init() -> void: add_to_group('interact') From 34c3f1311db6ba3f779db9763b5e8ad4404bb96d Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Fri, 19 Apr 2024 11:09:23 -0400 Subject: [PATCH 75/86] cleaned and added extra functions for menu --- src/autoloads/player_state.gd | 20 ++++++++---------- src/dialogue/main.dialogue | 2 +- src/main/menu_layer.gd | 40 +++++++++++++++++++++++------------ src/menu/menu_layer.tscn | 11 ++++++---- src/player/player.gd | 12 ++++++++--- 5 files changed, 52 insertions(+), 33 deletions(-) diff --git a/src/autoloads/player_state.gd b/src/autoloads/player_state.gd index 8e863ac..d6961d4 100644 --- a/src/autoloads/player_state.gd +++ b/src/autoloads/player_state.gd @@ -1,22 +1,20 @@ extends Node -# these are functions that can be called in the dialog system -# should probably re-name to something more descriptive +# these are functions that are meant to be called in the dialog system +# should probably re-name this script to something more descriptive -func has_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - return player.has_boots -func _give_boots(): - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - ItemDb.give_item("test0") - ItemDb.give_item("test1") +func _give_item(id:String): + ItemDb.give_item(id) #var ui = current_scene.get_node("UI") #ui.bootIcon.visible = true +func _has_item(item_id) -> bool: + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + return player.has_item(item_id) + # this value keeps changing based on the amount of autoloads we have diff --git a/src/dialogue/main.dialogue b/src/dialogue/main.dialogue index 7b4dec4..dfbb0f5 100644 --- a/src/dialogue/main.dialogue +++ b/src/dialogue/main.dialogue @@ -2,7 +2,7 @@ #if PlayerState.has_boots() == false boots? -do PlayerState._give_boots() +do PlayerState._give_item("test0") #else: => END \ No newline at end of file diff --git a/src/main/menu_layer.gd b/src/main/menu_layer.gd index 1aea3a0..c7670cc 100644 --- a/src/main/menu_layer.gd +++ b/src/main/menu_layer.gd @@ -1,7 +1,6 @@ extends CanvasLayer class_name Menu - @onready var itemDesc:Label = %ItemDesc @onready var itemTitle:Label = %ItemTitle @onready var itemGrid:GridContainer = %ItemGrid @@ -24,8 +23,6 @@ func equip_item(): var current_item = itemGrid.get_child(current_item_index) player.equipped_item = current_item equippedIcon.texture = load("res://assets/item_icons/" +ItemDb.ITEMS[current_item.id]['icon']) - itemTitle.text = ItemDb.ITEMS[current_item.id]['title'] - itemDesc.text = ItemDb.ITEMS[current_item.id]['description'] func get_input_vector(event: InputEvent) -> Vector2: @@ -54,6 +51,9 @@ func _input(event: InputEvent) -> void: _move_cursor(_input_dir) func _move_cursor(input_dir) -> void: + if itemGrid.get_child_count() == 0: + return + #cursor is 16 + 16 * pos #offset is pos - 1 * 8 if abs(input_dir.x) > 0: @@ -65,32 +65,44 @@ func _move_cursor(input_dir) -> void: var current_item_index = cursor_pos.x + (cursor_pos.y * item_grid_bounds.x) var current_item = itemGrid.get_child(current_item_index) - itemTitle.text = ItemDb.ITEMS[current_item.id]['title'] - itemDesc.text = ItemDb.ITEMS[current_item.id]['description'] - - - - + _update_labels(current_item.id) func _load_items(new_inventory:Array) -> void: + #clear existing inventory for child in itemGrid.get_children(): + itemGrid.remove_child(child) child.queue_free() + player_inventory = new_inventory + + if player_inventory.size() == 0: + return + + prints("sizes",itemGrid.get_child_count(),player_inventory.size()) + for item in player_inventory: var new_item_icon :TextureRect= item_icon_scene.instantiate() # we just store the id of the item in the icon, not the entire resource new_item_icon.id = item.id new_item_icon.texture = load("res://assets/item_icons/" +ItemDb.ITEMS[item.id]['icon']) itemGrid.add_child(new_item_icon) - item_grid_bounds.x = itemGrid.columns - # math to find row count based on number of children - item_grid_bounds.y = ceili(float(itemGrid.get_child_count())/float(itemGrid.columns)) - print("item grid bounds: ", item_grid_bounds) - + # math to find row and col count based on number of children + for child in itemGrid.get_children(): + print(child.id) + print(itemGrid.get_children()) + print(itemGrid.get_child_count()) + item_grid_bounds.x = min(itemGrid.get_child_count(),itemGrid.columns) + item_grid_bounds.y = ceili(float(itemGrid.get_child_count())/float(itemGrid.columns)) + print(item_grid_bounds) + _update_labels(itemGrid.get_child(0).id) +# update title and description +func _update_labels(item_id:String): + itemTitle.text = ItemDb.ITEMS[item_id]['title'] + itemDesc.text = ItemDb.ITEMS[item_id]['description'] diff --git a/src/menu/menu_layer.tscn b/src/menu/menu_layer.tscn index b149a01..a11e294 100644 --- a/src/menu/menu_layer.tscn +++ b/src/menu/menu_layer.tscn @@ -45,14 +45,15 @@ layout_mode = 2 unique_name_in_owner = true layout_mode = 2 size_flags_vertical = 0 -text = "adfasdfasdf" +text = "item name" autowrap_mode = 2 +uppercase = true [node name="ItemDesc" type="Label" parent="Menu/TextPanel/MarginContainer/VBoxContainer"] unique_name_in_owner = true layout_mode = 2 size_flags_vertical = 0 -text = "Same thing happend to my buddy eric." +text = "the Items description." autowrap_mode = 2 [node name="ItemPanel" type="Panel" parent="Menu"] @@ -68,8 +69,10 @@ theme = ExtResource("2_aexfy") [node name="ItemCursor" type="TextureRect" parent="Menu/ItemPanel"] unique_name_in_owner = true layout_mode = 2 -offset_right = 16.0 -offset_bottom = 16.0 +offset_left = 16.0 +offset_top = 16.0 +offset_right = 32.0 +offset_bottom = 32.0 size_flags_horizontal = 0 size_flags_vertical = 0 texture = ExtResource("3_8ywvp") diff --git a/src/player/player.gd b/src/player/player.gd index 0b9eb24..74257de 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -84,6 +84,12 @@ func give_boots(): has_boots = true -# we'd need to filter the array for id's, later problem -#func has_item(id:String) -> bool: - #return inventory.has() +func has_item(id:String) -> bool: + for item in inventory: + if item.id == id: + return true + return false + +func has_item_equipped(id:String) -> bool: + return equipped_item.id == id + From 629c35d7d46e25617598dbe2847b2717aba482d7 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sun, 21 Apr 2024 10:53:45 -0400 Subject: [PATCH 76/86] cleaning up the codebase --- assets/item_icons/x.png | Bin 201 -> 0 bytes assets/item_icons/x.png.import | 34 -------------- assets/maze_assets_very_temp/Apparatus.png | Bin 201 -> 0 bytes .../Apparatus.png.import | 34 -------------- assets/maze_assets_very_temp/Grid.png | Bin 139 -> 0 bytes assets/maze_assets_very_temp/Grid.png.import | 34 -------------- .../maze_assets_very_temp/MazeCharacter.png | Bin 181 -> 0 bytes .../MazeCharacter.png.import | 34 -------------- .../OutsideCharacter.png | Bin 187 -> 0 bytes .../OutsideCharacter.png.import | 34 -------------- assets/maze_assets_very_temp/PIECE.png | Bin 148 -> 0 bytes assets/maze_assets_very_temp/PIECE.png.import | 34 -------------- assets/maze_assets_very_temp/Wall.png | Bin 256 -> 0 bytes assets/maze_assets_very_temp/Wall.png.import | 34 -------------- assets/menu_arrow.png | Bin 119 -> 0 bytes assets/menu_arrow.png.import | 34 -------------- src/items/{item_res.gd => item.gd} | 0 src/items/item_db.gd | 2 +- src/items/test_item.tres | 9 ---- src/main/main.gd | 44 ++---------------- src/main/main.tscn | 1 + src/main/menu_layer.gd | 13 ++---- src/maps/map-0.tscn | 27 +++++++++++ src/maps/map-1.tscn | 1 - src/maps/map-2.tscn | 2 - src/maps/map-3.tscn | 4 +- src/maps/map-4.tscn | 17 ------- src/maps/map.gd | 2 +- src/menu/item_ui.tscn | 4 +- src/player/player.gd | 2 +- src/scene-tiles/stairs/stairs.gd | 2 +- todo.md | 11 +++-- 32 files changed, 47 insertions(+), 366 deletions(-) delete mode 100644 assets/item_icons/x.png delete mode 100644 assets/item_icons/x.png.import delete mode 100644 assets/maze_assets_very_temp/Apparatus.png delete mode 100644 assets/maze_assets_very_temp/Apparatus.png.import delete mode 100644 assets/maze_assets_very_temp/Grid.png delete mode 100644 assets/maze_assets_very_temp/Grid.png.import delete mode 100644 assets/maze_assets_very_temp/MazeCharacter.png delete mode 100644 assets/maze_assets_very_temp/MazeCharacter.png.import delete mode 100644 assets/maze_assets_very_temp/OutsideCharacter.png delete mode 100644 assets/maze_assets_very_temp/OutsideCharacter.png.import delete mode 100644 assets/maze_assets_very_temp/PIECE.png delete mode 100644 assets/maze_assets_very_temp/PIECE.png.import delete mode 100644 assets/maze_assets_very_temp/Wall.png delete mode 100644 assets/maze_assets_very_temp/Wall.png.import delete mode 100644 assets/menu_arrow.png delete mode 100644 assets/menu_arrow.png.import rename src/items/{item_res.gd => item.gd} (100%) delete mode 100644 src/items/test_item.tres create mode 100644 src/maps/map-0.tscn delete mode 100644 src/maps/map-4.tscn diff --git a/assets/item_icons/x.png b/assets/item_icons/x.png deleted file mode 100644 index 36598307451b577b14dd7cfd3f257a15bcba5a5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|nmt_{Lo9md zPCm_hK!L}3?mOn+?<Y2%S{jmB=XRF&#AX>DhKApoGSl9Q^LKR^+*qf7?ZCMuHU)m0 z<U(6Zc%zpz#j~q_Gp;x%so&EXVPTP=B*!*MBqGwH^nlxkmw$G-XkR+EBV8_eijv85 z+v2Z&hvH8>IG5_Nuxahv^YcRAJvh_3Dv5D+R{hh62!0u$a~M2b{an^LB{Ts5;M7g% diff --git a/assets/item_icons/x.png.import b/assets/item_icons/x.png.import deleted file mode 100644 index 9bea815..0000000 --- a/assets/item_icons/x.png.import +++ /dev/null @@ -1,34 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://bk51v1m1wfhex" -path="res://.godot/imported/x.png-3ec7665c51167d707c62ab68705ebe01.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/item_icons/x.png" -dest_files=["res://.godot/imported/x.png-3ec7665c51167d707c62ab68705ebe01.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 diff --git a/assets/maze_assets_very_temp/Apparatus.png b/assets/maze_assets_very_temp/Apparatus.png deleted file mode 100644 index b0931bc52061c24f0c149a9d5f321c9a7a17eb11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAIjKx9jP7LeL$-D$|nmt_{Lp;2b zQx-5MENPbISv+lm$SG W}-F|Jf_EKc~cPX#Ow%==Xm;FP=BS57o;LB#HcHNjdrK z<em=?e%E*OH(q=vd^lQC^i?F2sq7nR6Nc{$N9`7FS3SYU_OnOLPI7C@i=JK~_62W@ yq||>L>eD;eYW``()W`0+idOvsAr>`{SQrw8)TH!HJk^2DVeoYIb6Mw<&;$Tu?n?Cl diff --git a/assets/maze_assets_very_temp/Apparatus.png.import b/assets/maze_assets_very_temp/Apparatus.png.import deleted file mode 100644 index a67ce0c..0000000 --- a/assets/maze_assets_very_temp/Apparatus.png.import +++ /dev/null @@ -1,34 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://d302b6tly3nlg" -path="res://.godot/imported/Apparatus.png-f9b503bb50b0124c6d6ec56d99f778e5.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/maze_assets_very_temp/Apparatus.png" -dest_files=["res://.godot/imported/Apparatus.png-f9b503bb50b0124c6d6ec56d99f778e5.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 diff --git a/assets/maze_assets_very_temp/Grid.png b/assets/maze_assets_very_temp/Grid.png deleted file mode 100644 index 31886cfe4a3c5b71346741455a9543730ab7823d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAIjKx9jP7LeL$-D$|Ts>VJLp;2b z|NQ^|zn)Es*=>Sq4-jnG#GdnSh3XNu_ZbC((m@HOiw~Mg#Vk%0e`sPb%b%lNa8lRB k2U0H&x=#9kGJuD{Y3KfJ$;(yMfd(>oy85}Sb4q9e04<L%ZU6uP diff --git a/assets/maze_assets_very_temp/Grid.png.import b/assets/maze_assets_very_temp/Grid.png.import deleted file mode 100644 index a314d1d..0000000 --- a/assets/maze_assets_very_temp/Grid.png.import +++ /dev/null @@ -1,34 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://do7bbh25fyxkk" -path="res://.godot/imported/Grid.png-ad2a2c41ec4c4fc757ca16ddd2ccf88c.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/maze_assets_very_temp/Grid.png" -dest_files=["res://.godot/imported/Grid.png-ad2a2c41ec4c4fc757ca16ddd2ccf88c.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 diff --git a/assets/maze_assets_very_temp/MazeCharacter.png b/assets/maze_assets_very_temp/MazeCharacter.png deleted file mode 100644 index a73fd87c0db4309bd73c5e12d1f890d24a191632..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 181 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAIjKx9jP7LeL$-D$|@;zM~Lp;3S zP7dTcpuppN_Ame4hYOUVc0F5e&{3cCb*bUejEIZ`9!HJo)o+cA7e5j0V%+1q#&4g( z=DO>J@08VeH97Wsu`G<){pM6&`oa(Gn|?2~6g;9kC05(#zvuMh=0S7jzAX;^Rgrb3 eImuCjUA}jPo75JsRZD?ZGkCiCxvX<aXaWFs??jUT diff --git a/assets/maze_assets_very_temp/MazeCharacter.png.import b/assets/maze_assets_very_temp/MazeCharacter.png.import deleted file mode 100644 index cad9026..0000000 --- a/assets/maze_assets_very_temp/MazeCharacter.png.import +++ /dev/null @@ -1,34 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://df17dmyxpjmrb" -path="res://.godot/imported/MazeCharacter.png-1adff022473e8a0c9b50c7125d4e9d74.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/maze_assets_very_temp/MazeCharacter.png" -dest_files=["res://.godot/imported/MazeCharacter.png-1adff022473e8a0c9b50c7125d4e9d74.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 diff --git a/assets/maze_assets_very_temp/OutsideCharacter.png b/assets/maze_assets_very_temp/OutsideCharacter.png deleted file mode 100644 index 368a5875414dd46231c67e19dafe132effb7e454..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAIjKx9jP7LeL$-D$|N<Cd1Lp;3S zPCd)VAi&dH`M+JwT1T*cuG($JbFaK_D=u%C$}I6x*CSJD=^W)i?f|h%Jf_MAZ3Q;I zyVv<lTS4UQr&E!w3k9^So-CQKx20ZcW~hji_}6*+9=mjlA1~40z2ld2tit9=niIBG kWUYF!zj0x$y8Ft|<S)Wf+%_lbfDT~rboFyt=akR{0Juj(?f?J) diff --git a/assets/maze_assets_very_temp/OutsideCharacter.png.import b/assets/maze_assets_very_temp/OutsideCharacter.png.import deleted file mode 100644 index 3bad444..0000000 --- a/assets/maze_assets_very_temp/OutsideCharacter.png.import +++ /dev/null @@ -1,34 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://d316msy0elqvi" -path="res://.godot/imported/OutsideCharacter.png-b14b58cfbf9b1e85f3e2ae1f4605a240.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/maze_assets_very_temp/OutsideCharacter.png" -dest_files=["res://.godot/imported/OutsideCharacter.png-b14b58cfbf9b1e85f3e2ae1f4605a240.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 diff --git a/assets/maze_assets_very_temp/PIECE.png b/assets/maze_assets_very_temp/PIECE.png deleted file mode 100644 index 6abbe7ce31d100022609cbd12f0132c0b7cf0535..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAIjKx9jP7LeL$-D$|{5)M8Lp;2b z|I~N9w`cBUe7r(+Ny~?ff{8*=Jc|#SO2yo8eh@oFqWQw6aEs>l2{s<e_pY!SGfa1E ud6K9n?R#jk=Zqx+3Z5S`UP&!H$jZ=R5n&M`KhGOzGJ~h9pUXO@geCy9#W5lP diff --git a/assets/maze_assets_very_temp/PIECE.png.import b/assets/maze_assets_very_temp/PIECE.png.import deleted file mode 100644 index 781b608..0000000 --- a/assets/maze_assets_very_temp/PIECE.png.import +++ /dev/null @@ -1,34 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://hxb0etclpd4v" -path="res://.godot/imported/PIECE.png-0c51bb86246e0dfac67c8c365092f7f1.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/maze_assets_very_temp/PIECE.png" -dest_files=["res://.godot/imported/PIECE.png-0c51bb86246e0dfac67c8c365092f7f1.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 diff --git a/assets/maze_assets_very_temp/Wall.png b/assets/maze_assets_very_temp/Wall.png deleted file mode 100644 index d3f3ce36a011c971040d30e5fd44d01781e57666..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmV+b0ssDqP)<h;3K|Lk000e1NJLTq000>P000>X1^@s6#OZ}&00001b5ch_0Itp) z=>Px#x=BPqR7gwhR?!ZCAPCH#_9Oi1nr=8U;eg_;UfhcFMDC!{T03j4<p2-Gt*Zq$ zHn$K(NC-1CKtx^=zTfSdG$Iely3eB)5|Nc;hu;=_7ib}o4k)T>1t1dbs#WQ7phkj3 z6ZVJ4FOY<M)YooWzB#=^h8!Ri^!B?c6P^txw6voh|7YSVlc^>oj<CAWkt7p-=96^C zr}wV(E}TA3(kCNo*Jz%sDt*j&M8N-OJkq7u*}9{CvEVK+D2+NOePFNv0000<MNUMn GLSTXb>1sg$ diff --git a/assets/maze_assets_very_temp/Wall.png.import b/assets/maze_assets_very_temp/Wall.png.import deleted file mode 100644 index 6ab979e..0000000 --- a/assets/maze_assets_very_temp/Wall.png.import +++ /dev/null @@ -1,34 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://cn1dvcdverrmh" -path="res://.godot/imported/Wall.png-11c6891435809f4bbf36dfde0c97af57.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/maze_assets_very_temp/Wall.png" -dest_files=["res://.godot/imported/Wall.png-11c6891435809f4bbf36dfde0c97af57.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 diff --git a/assets/menu_arrow.png b/assets/menu_arrow.png deleted file mode 100644 index 4542eac291f5d0e087b936f12b82eee8fae819bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 119 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqjKx9jP7LeL$-D$|3_V>OLnNm5 z_BnDf81NjL_4ohzcTrB^&wP6_rcP10E6?0ku$Vi6b)N8jh65D^b4x22gRG^$-diJX Q2-M8r>FVdQ&MBb@03qijG5`Po diff --git a/assets/menu_arrow.png.import b/assets/menu_arrow.png.import deleted file mode 100644 index 2dd3f5c..0000000 --- a/assets/menu_arrow.png.import +++ /dev/null @@ -1,34 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://bbi13ou2tmyip" -path="res://.godot/imported/menu_arrow.png-2e32d3585e0043243fe1bb1337347455.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/menu_arrow.png" -dest_files=["res://.godot/imported/menu_arrow.png-2e32d3585e0043243fe1bb1337347455.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 diff --git a/src/items/item_res.gd b/src/items/item.gd similarity index 100% rename from src/items/item_res.gd rename to src/items/item.gd diff --git a/src/items/item_db.gd b/src/items/item_db.gd index 8e84233..5b43af5 100644 --- a/src/items/item_db.gd +++ b/src/items/item_db.gd @@ -32,7 +32,7 @@ func give_item(id:String) -> void: var player:Player = current_scene.get_node("Player") #if player.has_item(new_item) == false or new_item["unique"] == false: player.inventory.append(new_item) - print('player now has item: ', new_item) + print('player now has item: ', new_item.title) func _get_current_scene(): diff --git a/src/items/test_item.tres b/src/items/test_item.tres deleted file mode 100644 index 4e0fa23..0000000 --- a/src/items/test_item.tres +++ /dev/null @@ -1,9 +0,0 @@ -[gd_resource type="Resource" script_class="Item" load_steps=2 format=3 uid="uid://c5ru2507ecm8f"] - -[ext_resource type="Script" path="res://src/items/item.gd" id="1_b1mog"] - -[resource] -script = ExtResource("1_b1mog") -id = 0 -ui_name = "" -description = "" diff --git a/src/main/main.gd b/src/main/main.gd index 54d4068..a50ac92 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -3,16 +3,6 @@ extends Node2D @onready var menuLayer = $MenuLayer @onready var player:Player = $Player @onready var current_map:Node2D = $Map -var in_cutscene := false - -var maps:Array = [preload('res://src/maps/map-1.tscn'),preload('res://src/maps/map-2.tscn'),preload('res://src/maps/map-3.tscn')] -var map_room_id_dict: Dictionary = { #Not perfect but works for time constraint - 1 : preload('res://src/maps/map-1.tscn'), - 2: preload('res://src/maps/map-2.tscn'), - 3: preload('res://src/maps/map-3.tscn') -} - -var shuffled_maps:Array = [] var current_map_id @@ -22,28 +12,9 @@ func _ready() -> void: player.walked_into_stairs.connect(next_map) pass -func next_map(given_room_id: int) -> void: - var next_map_id :int = given_room_id - var nextMap:Node2D = map_room_id_dict[next_map_id].instantiate() - #load new map - current_map.queue_free() - add_child(nextMap) - current_map = nextMap - - #move the player to the spawn point - var playerSpawnMarker:Marker2D = nextMap.get_node('PlayerSpawn') - player.position = playerSpawnMarker.position - pass - -func swap_map() -> void: - #reshuffle rooms if we've visted them all - if shuffled_maps.size() == 0: - shuffled_maps = Array(range(maps.size())) - shuffled_maps.shuffle() - #pick new room from remaining choices - var next_map_id :int = shuffled_maps.pop_front() - var nextMap:Node2D = maps[next_map_id].instantiate() - +func next_map(next_room_id: int) -> void: + var next_map_path :String = "res://src/maps/map-%s.tscn" % str(next_room_id) + var nextMap:Map = load(next_map_path).instantiate() #load new map current_map.queue_free() add_child(nextMap) @@ -58,12 +29,3 @@ func _toggle_menu(inventory) -> void: menuLayer._load_items(inventory) pass -#unused, will remove later -#func _start_cutscene() -> void: - #in_cutscene = true - #player.is_actionable = false - -#func _end_cutscene() -> void: - #in_cutscene = false - #await get_tree().create_timer(0.01).timeout # 10ms buffer hack to prevent input collision from text advancing and player input, could also solve by checking UI input in player _input event? - #player.is_actionable = true diff --git a/src/main/main.tscn b/src/main/main.tscn index 3b9aa8d..9834acc 100644 --- a/src/main/main.tscn +++ b/src/main/main.tscn @@ -20,6 +20,7 @@ position = Vector2(80, 48) [node name="Map" parent="." instance=ExtResource("3_w444g")] [node name="HUD" type="Control" parent="."] +z_index = 10 layout_mode = 3 anchors_preset = 0 offset_right = 256.0 diff --git a/src/main/menu_layer.gd b/src/main/menu_layer.gd index c7670cc..cc91ca0 100644 --- a/src/main/menu_layer.gd +++ b/src/main/menu_layer.gd @@ -18,11 +18,12 @@ var player_inventory :Array = [] var item_grid_bounds:= Vector2i(0,0) func equip_item(): + if itemGrid.get_child_count() == 0: + return var current_item_index = cursor_pos.x + (cursor_pos.y * item_grid_bounds.x) - print("pulled child: ",current_item_index) var current_item = itemGrid.get_child(current_item_index) player.equipped_item = current_item - equippedIcon.texture = load("res://assets/item_icons/" +ItemDb.ITEMS[current_item.id]['icon']) + equippedIcon.texture = load("res://assets/item_icons/%s" % ItemDb.ITEMS[current_item.id]['icon']) func get_input_vector(event: InputEvent) -> Vector2: @@ -78,23 +79,17 @@ func _load_items(new_inventory:Array) -> void: if player_inventory.size() == 0: return - prints("sizes",itemGrid.get_child_count(),player_inventory.size()) for item in player_inventory: var new_item_icon :TextureRect= item_icon_scene.instantiate() # we just store the id of the item in the icon, not the entire resource new_item_icon.id = item.id - new_item_icon.texture = load("res://assets/item_icons/" +ItemDb.ITEMS[item.id]['icon']) + new_item_icon.texture = load("res://assets/item_icons/%s" %ItemDb.ITEMS[item.id]['icon']) itemGrid.add_child(new_item_icon) # math to find row and col count based on number of children - for child in itemGrid.get_children(): - print(child.id) - print(itemGrid.get_children()) - print(itemGrid.get_child_count()) item_grid_bounds.x = min(itemGrid.get_child_count(),itemGrid.columns) item_grid_bounds.y = ceili(float(itemGrid.get_child_count())/float(itemGrid.columns)) - print(item_grid_bounds) _update_labels(itemGrid.get_child(0).id) diff --git a/src/maps/map-0.tscn b/src/maps/map-0.tscn new file mode 100644 index 0000000..b08352c --- /dev/null +++ b/src/maps/map-0.tscn @@ -0,0 +1,27 @@ +[gd_scene load_steps=6 format=3 uid="uid://22clf0thbdqv"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_k21k7"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_7hcry"] +[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="3_srxud"] +[ext_resource type="Resource" uid="uid://dlw5a1hy61hj8" path="res://src/dialogue/main.dialogue" id="4_q2eeb"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="5_lbiou"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_k21k7") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_7hcry") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 48) + +[node name="Chest" parent="." instance=ExtResource("3_srxud")] +position = Vector2(160, 96) +dialog_resource = ExtResource("4_q2eeb") + +[node name="stairs" parent="." instance=ExtResource("5_lbiou")] +position = Vector2(112, 48) diff --git a/src/maps/map-1.tscn b/src/maps/map-1.tscn index 7459311..b009704 100644 --- a/src/maps/map-1.tscn +++ b/src/maps/map-1.tscn @@ -21,7 +21,6 @@ position = Vector2(80, 48) [node name="stairs" parent="." instance=ExtResource("3_8x2ye")] position = Vector2(160, 96) -toward_room_id = 2 [node name="Chest" parent="." instance=ExtResource("4_hq2kf")] position = Vector2(112, 64) diff --git a/src/maps/map-2.tscn b/src/maps/map-2.tscn index 96ad0c4..f908471 100644 --- a/src/maps/map-2.tscn +++ b/src/maps/map-2.tscn @@ -6,7 +6,6 @@ [node name="Map" type="Node2D"] script = ExtResource("1_wfc8d") -room_id = 2 [node name="TileMap" type="TileMap" parent="."] tile_set = ExtResource("1_2mk3g") @@ -20,4 +19,3 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_wvxh7")] position = Vector2(160, 96) -toward_room_id = 3 diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn index 8ca8799..263b88a 100644 --- a/src/maps/map-3.tscn +++ b/src/maps/map-3.tscn @@ -6,13 +6,12 @@ [node name="Map" type="Node2D"] script = ExtResource("1_kwl2f") -room_id = 3 [node name="TileMap" type="TileMap" parent="."] tile_set = ExtResource("1_xfyi1") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458762, 262145, 18, 458761, 262145, 18, 65550, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 262157, 262145, 18, 196621, 262145, 18, 196620, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 327688, 262145, 18, 393224, 262145, 18, 393223, 262145, 18, 327687, 262145, 18, 327686, 262145, 18, 262150, 262145, 18, 196614, 262145, 18, 196613, 262145, 18, 196612, 262145, 18, 262148, 262145, 18, 262147, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 327685, 262145, 18, 393225, 262145, 18, 393226, 262145, 18, 393227, 262145, 18, 393229, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 327693, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 196615, 262145, 18, 262151, 262145, 18, 131082, 3, 262144, 524300, 1245185, 2, 393228, 262145, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458762, 262145, 18, 458761, 262145, 18, 65550, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 262157, 262145, 18, 196621, 262145, 18, 196620, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 327688, 262145, 18, 393224, 262145, 18, 393223, 262145, 18, 327687, 262145, 18, 327686, 262145, 18, 262150, 262145, 18, 196614, 262145, 18, 196613, 262145, 18, 196612, 262145, 18, 262148, 262145, 18, 262147, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 327685, 262145, 18, 393225, 262145, 18, 393226, 262145, 18, 393227, 262145, 18, 393229, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 327693, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 196615, 262145, 18, 262151, 262145, 18, 524300, 1245185, 2, 393228, 262145, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -20,4 +19,3 @@ position = Vector2(144, 48) [node name="stairs" parent="." instance=ExtResource("3_vucpd")] position = Vector2(192, 80) -toward_room_id = 1 diff --git a/src/maps/map-4.tscn b/src/maps/map-4.tscn deleted file mode 100644 index 55e1f6a..0000000 --- a/src/maps/map-4.tscn +++ /dev/null @@ -1,17 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://22clf0thbdqv"] - -[ext_resource type="Script" path="res://src/maps/map.gd" id="1_qwjcs"] -[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_1bcx7"] - -[node name="Map" type="Node2D"] -script = ExtResource("1_qwjcs") - -[node name="TileMap" type="TileMap" parent="."] -tile_set = ExtResource("2_1bcx7") -format = 2 -layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 196615, 3, 262144, 393226, 3, 196608) -layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) - -[node name="PlayerSpawn" type="Marker2D" parent="."] -position = Vector2(80, 48) diff --git a/src/maps/map.gd b/src/maps/map.gd index 52bbc82..c041711 100644 --- a/src/maps/map.gd +++ b/src/maps/map.gd @@ -2,7 +2,7 @@ class_name Map extends Node2D # we need to add a collision shape to the tilemap for the player raycast to be able to detect it, otherwise it'll be considered null. - +var id:int @onready var tilemap:TileMap = $TileMap func _ready() -> void: diff --git a/src/menu/item_ui.tscn b/src/menu/item_ui.tscn index 72db49b..44f250b 100644 --- a/src/menu/item_ui.tscn +++ b/src/menu/item_ui.tscn @@ -1,8 +1,6 @@ -[gd_scene load_steps=3 format=3 uid="uid://dhi5ko8td6k8x"] +[gd_scene load_steps=2 format=3 uid="uid://dhi5ko8td6k8x"] -[ext_resource type="Texture2D" uid="uid://bk51v1m1wfhex" path="res://assets/item_icons/x.png" id="1_poc1b"] [ext_resource type="Script" path="res://src/menu/item_ui.gd" id="2_02iya"] [node name="TextureRect" type="TextureRect"] -texture = ExtResource("1_poc1b") script = ExtResource("2_02iya") diff --git a/src/player/player.gd b/src/player/player.gd index 74257de..ea43132 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -66,7 +66,7 @@ func check_next_tile(tile: Object) -> void: if tile == null: return if tile.is_in_group('stairs'): - walked_into_stairs.emit(tile.toward_room_id) + walked_into_stairs.emit(tile.next_room_id) func _interact() -> void: raycast.force_raycast_update() diff --git a/src/scene-tiles/stairs/stairs.gd b/src/scene-tiles/stairs/stairs.gd index 4ea5add..e38d74a 100644 --- a/src/scene-tiles/stairs/stairs.gd +++ b/src/scene-tiles/stairs/stairs.gd @@ -1,6 +1,6 @@ extends Area2D -@export var toward_room_id: int = 0 +@export var next_room_id: int = 0 # Called when the node enters the scene tree for the first time. func _ready() -> void: diff --git a/todo.md b/todo.md index 92ff736..ea01a5d 100644 --- a/todo.md +++ b/todo.md @@ -18,8 +18,9 @@ # todo: -- use grid nodes -- change db to use names instead of numbers -- render items to the game when the menu loads -- fix input issues with canvas layer -- update currently equipped one \ No newline at end of file +- clean things up +- update contribution instructions +- work on settings menu: + - control mapping? + - resolution scale, integer or fit + - \ No newline at end of file From bf0c3ceec74dc66933ec61ea3eeafd19daf78428 Mon Sep 17 00:00:00 2001 From: Tigran <122690491+TigranExe@users.noreply.github.com> Date: Sun, 21 Apr 2024 10:45:42 -0400 Subject: [PATCH 77/86] Teleportation And Preparing for next levels --- src/boots/boots.gd | 24 +++++++++++++++++++++--- src/boots/boots.tscn | 12 ++++++++++++ src/items/item.gd | 2 +- src/items/item_db.gd | 38 +++++++++++++++++++------------------- src/main/main.gd | 39 ++++++++++++++++++++++++++++++++------- src/maps/map-10.tscn | 26 ++++++++++++++++++++++++++ src/maps/map-11.tscn | 26 ++++++++++++++++++++++++++ src/maps/map-2.tscn | 9 +++++---- src/maps/map-3.tscn | 11 ++++++++--- src/maps/map-5.tscn | 26 ++++++++++++++++++++++++++ src/maps/map-6.tscn | 26 ++++++++++++++++++++++++++ src/maps/map-7.tscn | 26 ++++++++++++++++++++++++++ src/maps/map-77.tscn | 26 ++++++++++++++++++++++++++ src/maps/map-8.tscn | 26 ++++++++++++++++++++++++++ src/maps/map-9.tscn | 26 ++++++++++++++++++++++++++ src/player/player.tscn | 5 ++++- 16 files changed, 310 insertions(+), 38 deletions(-) create mode 100644 src/maps/map-10.tscn create mode 100644 src/maps/map-11.tscn create mode 100644 src/maps/map-5.tscn create mode 100644 src/maps/map-6.tscn create mode 100644 src/maps/map-7.tscn create mode 100644 src/maps/map-77.tscn create mode 100644 src/maps/map-8.tscn create mode 100644 src/maps/map-9.tscn diff --git a/src/boots/boots.gd b/src/boots/boots.gd index fa7a0cc..58f96e1 100644 --- a/src/boots/boots.gd +++ b/src/boots/boots.gd @@ -1,36 +1,54 @@ extends Node2D -var move_code: Array[String] = ["down","down","down","down","down"] -var recent_moves: Array[String] = ["","","","",""] +var winning_move_code: Array[String] = ["down","down","down","down","down","right"] +var teleport_move_code: Array[String] = ["down","up","down","up"] +var recent_moves: Array[String] = ["","","","","",""] # Called when the node enters the scene tree for the first time. +signal teleport_requested() func _ready() -> void: print("BOOTS ON!!!") connect_to_player() + connect_to_main() + func connect_to_player() -> void: var player := get_parent() player.moved.connect(player_moved) +func connect_to_main() -> void: + var main := get_parent().get_parent() + self.connect("teleport_requested", Callable(main, "on_teleport_requested")) + func player_moved(dir: Vector2) -> void: match dir: Vector2(0,1): push_move("down") + $DownSound.play() pass Vector2(0,-1): push_move("up") + $UpSound.play() pass Vector2(1,0): push_move("right") + $RightSound.play() pass Vector2(-1,0): push_move("left") + $LeftSound.play() pass + check_move_codes() - if recent_moves == move_code: +func check_move_codes(): + if recent_moves == winning_move_code: code_entered() + if recent_moves.slice(1,-1) == teleport_move_code: + teleport_requested.emit() + pass + pass func push_move(dir_string: String) -> void: recent_moves.pop_front() diff --git a/src/boots/boots.tscn b/src/boots/boots.tscn index f9fcf8b..b52f95a 100644 --- a/src/boots/boots.tscn +++ b/src/boots/boots.tscn @@ -4,3 +4,15 @@ [node name="Boots" type="Node2D"] script = ExtResource("1_1p87s") + +[node name="UpSound" type="AudioStreamPlayer2D" parent="."] +position = Vector2(0, -99) + +[node name="DownSound" type="AudioStreamPlayer2D" parent="."] +position = Vector2(0, 99) + +[node name="LeftSound" type="AudioStreamPlayer2D" parent="."] +position = Vector2(-99, 0) + +[node name="RightSound" type="AudioStreamPlayer2D" parent="."] +position = Vector2(99, 0) diff --git a/src/items/item.gd b/src/items/item.gd index 1c7d70e..15a4501 100644 --- a/src/items/item.gd +++ b/src/items/item.gd @@ -11,4 +11,4 @@ func given_to_player(): in_inventory = true func removed_from_player(): - in_inventory = false \ No newline at end of file + in_inventory = false diff --git a/src/items/item_db.gd b/src/items/item_db.gd index 5b43af5..ae28209 100644 --- a/src/items/item_db.gd +++ b/src/items/item_db.gd @@ -4,28 +4,28 @@ extends Node #currently auto-loaded, although I think we could get away with it being a static script, as it dosen't have any instanced values we need to maintain, const ITEMS = { - "test0":{ - "title": "TEST ITEM", - "icon":"sword.png", - "description":"You shouldn't have this item.", - "unique":true, - }, - "test1":{ - "title":"TEST ITEM 2", - "icon":"pendant.png", - "description":"You (also) shouldn't have this item.", - "unique":true, - } + "test0":{ + "title": "TEST ITEM", + "icon":"sword.png", + "description":"You shouldn't have this item.", + "unique":true, + }, + "test1":{ + "title":"TEST ITEM 2", + "icon":"pendant.png", + "description":"You (also) shouldn't have this item.", + "unique":true, + } } # item constructor func give_item(id:String) -> void: - var new_item:Item = Item.new() - new_item.id = id - new_item.title = ITEMS[id]["title"] - var icon_name = ITEMS[id]["icon"] - new_item.icon = load("res://assets/item_icons/" + icon_name) - new_item.description = ITEMS[id]["description"] + var new_item:Item = Item.new() + new_item.id = id + new_item.title = ITEMS[id]["title"] + var icon_name = ITEMS[id]["icon"] + new_item.icon = load("res://assets/item_icons/" + icon_name) + new_item.description = ITEMS[id]["description"] # add resource to player inventory var current_scene = _get_current_scene() @@ -36,6 +36,6 @@ func give_item(id:String) -> void: func _get_current_scene(): - return get_tree().get_root().get_children()[-1] + return get_tree().get_root().get_children()[-1] diff --git a/src/main/main.gd b/src/main/main.gd index a50ac92..2869c55 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -4,16 +4,13 @@ extends Node2D @onready var player:Player = $Player @onready var current_map:Node2D = $Map -var current_map_id +var current_map_id = 1 func _ready() -> void: - #ui.text_rendered.connect(_start_cutscene) - #ui.text_removed.connect(_end_cutscene) - player.walked_into_stairs.connect(next_map) - pass + player.walked_into_stairs.connect(change_map) -func next_map(next_room_id: int) -> void: - var next_map_path :String = "res://src/maps/map-%s.tscn" % str(next_room_id) +func change_map(next_map_id: int) -> void: + var next_map_path :String = "res://src/maps/map-%s.tscn" % str(next_map_id) var nextMap:Map = load(next_map_path).instantiate() #load new map current_map.queue_free() @@ -24,6 +21,34 @@ func next_map(next_room_id: int) -> void: var playerSpawnMarker:Marker2D = nextMap.get_node('PlayerSpawn') player.position = playerSpawnMarker.position +func on_teleport_entered() -> void: + var next_map_id :int = current_map_id + 2 + match current_map_id: + 77: + print("can't teleport") + 11: + next_map_id = 2 + 10: + next_map_id = 1 + _: + next_map_id = current_map_id + 2 + + var next_map_path :String = "res://src/maps/map-%s.tscn" % str(next_map_id) + var nextMap:Map = load(next_map_path).instantiate() + + #Check if you'd go to an empty tile + var potential_tile_position = nextMap.get_node("TileMap").local_to_map(player.position) + var potential_tile = nextMap.get_node("TileMap").get_cell_tile_data(0, potential_tile_position) + + if potential_tile != null: + print("can't teleport") + + # go to new map + current_map.queue_free() + add_child(nextMap) + current_map = nextMap + current_map_id = next_map_id + func _toggle_menu(inventory) -> void: menuLayer.visible = true menuLayer._load_items(inventory) diff --git a/src/maps/map-10.tscn b/src/maps/map-10.tscn new file mode 100644 index 0000000..cf7cc47 --- /dev/null +++ b/src/maps/map-10.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://tbdug0eavdeu"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_0dl14"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_f1sjl"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_l62f8"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_0dl14") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_f1sjl") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 64) + +[node name="stairs" parent="." instance=ExtResource("3_l62f8")] +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_l62f8")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-11.tscn b/src/maps/map-11.tscn new file mode 100644 index 0000000..c98dc1a --- /dev/null +++ b/src/maps/map-11.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://behqbmue4bheh"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_6lakl"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_l41to"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_1hxxh"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_6lakl") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_l41to") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 64) + +[node name="stairs" parent="." instance=ExtResource("3_1hxxh")] +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_1hxxh")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-2.tscn b/src/maps/map-2.tscn index f908471..a46ebf8 100644 --- a/src/maps/map-2.tscn +++ b/src/maps/map-2.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=4 format=3 uid="uid://cwxdotd7hh5tb"] +[gd_scene load_steps=4 format=3 uid="uid://bapnj7ekqfb0t"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_2mk3g"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_wfc8d"] @@ -11,11 +11,12 @@ script = ExtResource("1_wfc8d") tile_set = ExtResource("1_2mk3g") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458762, 262145, 18, 458761, 262145, 18, 65550, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 262157, 262145, 18, 196621, 262145, 18, 196620, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 327688, 262145, 18, 393224, 262145, 18, 393223, 262145, 18, 327687, 262145, 18, 327686, 262145, 18, 262150, 262145, 18, 196614, 262145, 18, 196613, 262145, 18, 196612, 262145, 18, 262148, 262145, 18, 262147, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 327685, 262145, 18, 393225, 262145, 18, 393226, 262145, 18, 393227, 262145, 18, 393229, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 327693, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 196615, 262145, 18, 262151, 262145, 18, 524300, 1245185, 2, 393228, 262145, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] -position = Vector2(80, 64) +position = Vector2(144, 48) [node name="stairs" parent="." instance=ExtResource("3_wvxh7")] -position = Vector2(160, 96) +position = Vector2(192, 80) +toward_room_id = 3 diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn index 263b88a..de2e7dd 100644 --- a/src/maps/map-3.tscn +++ b/src/maps/map-3.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=4 format=3 uid="uid://bapnj7ekqfb0t"] +[gd_scene load_steps=4 format=3 uid="uid://cwxdotd7hh5tb"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_kwl2f"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_xfyi1"] @@ -15,7 +15,12 @@ layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0 layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] -position = Vector2(144, 48) +position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_vucpd")] -position = Vector2(192, 80) +position = Vector2(160, 96) +toward_room_id = 1 + +[node name="stairs2" parent="." instance=ExtResource("3_vucpd")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-5.tscn b/src/maps/map-5.tscn new file mode 100644 index 0000000..633932b --- /dev/null +++ b/src/maps/map-5.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://cy6ft3gis6xo1"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_1iq0s"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_bw06a"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_oj5pp"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_1iq0s") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_bw06a") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 64) + +[node name="stairs" parent="." instance=ExtResource("3_oj5pp")] +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_oj5pp")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-6.tscn b/src/maps/map-6.tscn new file mode 100644 index 0000000..e39a009 --- /dev/null +++ b/src/maps/map-6.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://32pkjn8ivcow"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_8dqx8"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_iwcel"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_qk1jn"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_8dqx8") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_iwcel") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 64) + +[node name="stairs" parent="." instance=ExtResource("3_qk1jn")] +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_qk1jn")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-7.tscn b/src/maps/map-7.tscn new file mode 100644 index 0000000..07a8237 --- /dev/null +++ b/src/maps/map-7.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://qmrwu7f2fpg6"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_4rl4u"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_hcug5"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_3nspj"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_4rl4u") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_hcug5") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 64) + +[node name="stairs" parent="." instance=ExtResource("3_3nspj")] +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_3nspj")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-77.tscn b/src/maps/map-77.tscn new file mode 100644 index 0000000..e1cc1c3 --- /dev/null +++ b/src/maps/map-77.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://bhhcjxrvxxawg"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_f3vvj"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_l7q50"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_les7w"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_f3vvj") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_l7q50") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 64) + +[node name="stairs" parent="." instance=ExtResource("3_les7w")] +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_les7w")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-8.tscn b/src/maps/map-8.tscn new file mode 100644 index 0000000..8cf74f6 --- /dev/null +++ b/src/maps/map-8.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://bodeim6hge5e7"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_xna0b"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_s8tme"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_cycrh"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_xna0b") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_s8tme") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 64) + +[node name="stairs" parent="." instance=ExtResource("3_cycrh")] +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_cycrh")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-9.tscn b/src/maps/map-9.tscn new file mode 100644 index 0000000..e0a21d2 --- /dev/null +++ b/src/maps/map-9.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://b4qe43ry8jtg"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_ojfbm"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_tet7f"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_n0dp0"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_ojfbm") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_tet7f") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 64) + +[node name="stairs" parent="." instance=ExtResource("3_n0dp0")] +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_n0dp0")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/player/player.tscn b/src/player/player.tscn index 6c7d3be..c9aa73c 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=4 format=3 uid="uid://bp6oyjqvoyffq"] +[gd_scene load_steps=5 format=3 uid="uid://bp6oyjqvoyffq"] [ext_resource type="Texture2D" uid="uid://b3w5cmqr6fbcw" path="res://assets/monochrome-transparent_packed.png" id="1_bwexj"] [ext_resource type="Script" path="res://src/player/player.gd" id="1_fqi5k"] +[ext_resource type="PackedScene" uid="uid://dtgyaic6xsu0h" path="res://src/boots/boots.tscn" id="3_6ip46"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_v5s8d"] size = Vector2(16, 16) @@ -22,3 +23,5 @@ region_rect = Rect2(432, 0, 16, 16) [node name="RayCast2D" type="RayCast2D" parent="."] position = Vector2(8, 8) target_position = Vector2(0, 16) + +[node name="Boots" parent="." instance=ExtResource("3_6ip46")] From 1fe5fb3866b1b5a21727ae2ea0065e1570ac817c Mon Sep 17 00:00:00 2001 From: Tigran <122690491+TigranExe@users.noreply.github.com> Date: Sun, 21 Apr 2024 11:18:56 -0400 Subject: [PATCH 78/86] Map puzzles Now in! --- src/maps/map-1.tscn | 11 +++-------- src/maps/map-10.tscn | 10 +++------- src/maps/map-11.tscn | 22 +++++++++------------- src/maps/map-3.tscn | 6 +++--- src/maps/map-4.tscn | 22 ++++++++++++++++++++++ src/maps/map-5.tscn | 14 +++++++------- src/maps/map-6.tscn | 8 ++++---- src/maps/map-7.tscn | 8 ++------ src/maps/map-77.tscn | 9 ++------- src/maps/map-8.tscn | 10 +++------- src/maps/map-9.tscn | 12 ++++++++---- 11 files changed, 66 insertions(+), 66 deletions(-) create mode 100644 src/maps/map-4.tscn diff --git a/src/maps/map-1.tscn b/src/maps/map-1.tscn index b009704..094cd6c 100644 --- a/src/maps/map-1.tscn +++ b/src/maps/map-1.tscn @@ -1,10 +1,8 @@ -[gd_scene load_steps=6 format=3 uid="uid://deqm4to4ptnq0"] +[gd_scene load_steps=4 format=3 uid="uid://deqm4to4ptnq0"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="1_vosps"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_web8r"] [ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_8x2ye"] -[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="4_hq2kf"] -[ext_resource type="Resource" uid="uid://dlw5a1hy61hj8" path="res://src/dialogue/main.dialogue" id="5_gjl3f"] [node name="Map" type="Node2D"] script = ExtResource("1_web8r") @@ -13,7 +11,7 @@ script = ExtResource("1_web8r") tile_set = ExtResource("1_vosps") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 458754, 262145, 18, 458755, 262145, 18, 393219, 262145, 18, 327683, 262145, 18, 262147, 262145, 18, 196611, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 327682, 262145, 18, 393218, 262145, 18, 65537, 196609, 18, 65538, 196609, 18, 65539, 196609, 18, 65549, 196609, 18, 65550, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -21,7 +19,4 @@ position = Vector2(80, 48) [node name="stairs" parent="." instance=ExtResource("3_8x2ye")] position = Vector2(160, 96) - -[node name="Chest" parent="." instance=ExtResource("4_hq2kf")] -position = Vector2(112, 64) -dialog_resource = ExtResource("5_gjl3f") +toward_room_id = 2 diff --git a/src/maps/map-10.tscn b/src/maps/map-10.tscn index cf7cc47..2ccc5ed 100644 --- a/src/maps/map-10.tscn +++ b/src/maps/map-10.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=4 format=3 uid="uid://tbdug0eavdeu"] +[gd_scene load_steps=4 format=3 uid="uid://behqbmue4bheh"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_0dl14"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_f1sjl"] @@ -11,7 +11,7 @@ script = ExtResource("1_0dl14") tile_set = ExtResource("2_f1sjl") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -19,8 +19,4 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_l62f8")] position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_l62f8")] -position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 11 diff --git a/src/maps/map-11.tscn b/src/maps/map-11.tscn index c98dc1a..b3d5e87 100644 --- a/src/maps/map-11.tscn +++ b/src/maps/map-11.tscn @@ -1,26 +1,22 @@ -[gd_scene load_steps=4 format=3 uid="uid://behqbmue4bheh"] +[gd_scene load_steps=4 format=3 uid="uid://tbdug0eavdeu"] -[ext_resource type="Script" path="res://src/maps/map.gd" id="1_6lakl"] -[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_l41to"] -[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_1hxxh"] +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_0dl14"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_f1sjl"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_l62f8"] [node name="Map" type="Node2D"] -script = ExtResource("1_6lakl") +script = ExtResource("1_0dl14") [node name="TileMap" type="TileMap" parent="."] -tile_set = ExtResource("2_l41to") +tile_set = ExtResource("2_f1sjl") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524302, 1245185, 2, 524291, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 393218, 262145, 18, 327682, 262145, 18, 262146, 262145, 18, 196610, 262145, 18, 131074, 262145, 18, 393221, 262145, 18, 196613, 262145, 18, 131077, 262145, 18, 393224, 262145, 18, 327688, 262145, 18, 262152, 262145, 18, 196616, 262145, 18, 131080, 262145, 18, 393227, 262145, 18, 196619, 262145, 18, 131083, 262145, 18, 262155, 196609, 18, 327691, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) -[node name="stairs" parent="." instance=ExtResource("3_1hxxh")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_1hxxh")] +[node name="stairs" parent="." instance=ExtResource("3_l62f8")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 1 diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn index de2e7dd..d68246d 100644 --- a/src/maps/map-3.tscn +++ b/src/maps/map-3.tscn @@ -11,7 +11,7 @@ script = ExtResource("1_kwl2f") tile_set = ExtResource("1_xfyi1") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458762, 262145, 18, 458761, 262145, 18, 65550, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 262157, 262145, 18, 196621, 262145, 18, 196620, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 327688, 262145, 18, 393224, 262145, 18, 393223, 262145, 18, 327687, 262145, 18, 327686, 262145, 18, 262150, 262145, 18, 196614, 262145, 18, 196613, 262145, 18, 196612, 262145, 18, 262148, 262145, 18, 262147, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 327685, 262145, 18, 393225, 262145, 18, 393226, 262145, 18, 393227, 262145, 18, 393229, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 327693, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 196615, 262145, 18, 262151, 262145, 18, 524300, 1245185, 2, 393228, 262145, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 327690, 262145, 18, 262153, 262145, 18, 196616, 262145, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -19,8 +19,8 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_vucpd")] position = Vector2(160, 96) -toward_room_id = 1 +toward_room_id = 4 [node name="stairs2" parent="." instance=ExtResource("3_vucpd")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 77 diff --git a/src/maps/map-4.tscn b/src/maps/map-4.tscn new file mode 100644 index 0000000..9bd6d65 --- /dev/null +++ b/src/maps/map-4.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=4 format=3 uid="uid://22clf0thbdqv"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_qwjcs"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_1bcx7"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_w7jut"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_qwjcs") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_1bcx7") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 48) + +[node name="stairs" parent="." instance=ExtResource("3_w7jut")] +position = Vector2(192, 64) +toward_room_id = 5 diff --git a/src/maps/map-5.tscn b/src/maps/map-5.tscn index 633932b..0d0681b 100644 --- a/src/maps/map-5.tscn +++ b/src/maps/map-5.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=4 format=3 uid="uid://cy6ft3gis6xo1"] +[gd_scene load_steps=5 format=3 uid="uid://cy6ft3gis6xo1"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_1iq0s"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_bw06a"] [ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_oj5pp"] +[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="4_wwsf8"] [node name="Map" type="Node2D"] script = ExtResource("1_1iq0s") @@ -11,16 +12,15 @@ script = ExtResource("1_1iq0s") tile_set = ExtResource("2_bw06a") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 458754, 262145, 18, 393218, 262145, 18, 327682, 262145, 18, 262146, 262145, 18, 196610, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 131075, 262145, 18, 131076, 262145, 18, 196614, 262145, 18, 262147, 262145, 18, 262148, 262145, 18, 196611, 262145, 18, 196615, 262145, 18, 196616, 262145, 18, 262153, 262145, 18, 327690, 262145, 18, 327691, 262145, 18, 196612, 196609, 18, 196613, 196609, 18, 131077, 196609, 18, 131078, 196609, 18, 131079, 196609, 18, 131080, 196609, 18, 131081, 196609, 18, 196617, 196609, 18, 327689, 262145, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_oj5pp")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_oj5pp")] -position = Vector2(192, 48) +position = Vector2(112, 96) toward_room_id = 6 + +[node name="Chest" parent="." instance=ExtResource("4_wwsf8")] +position = Vector2(176, 48) diff --git a/src/maps/map-6.tscn b/src/maps/map-6.tscn index e39a009..467020e 100644 --- a/src/maps/map-6.tscn +++ b/src/maps/map-6.tscn @@ -11,16 +11,16 @@ script = ExtResource("1_8dqx8") tile_set = ExtResource("2_iwcel") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 524291, 1245185, 2, 196615, 262145, 18, 196616, 262145, 18, 131079, 262145, 18, 65544, 262145, 18, 65543, 262145, 18, 131080, 262145, 18, 196617, 262145, 18, 65545, 262145, 18, 131081, 262145, 18, 131082, 262145, 18, 196618, 262145, 18, 65546, 262145, 18, 458766, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 393229, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393228, 262145, 18, 327693, 262145, 18, 458755, 262145, 18, 458756, 262145, 18, 393219, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 65549, 262145, 18, 65550, 262145, 18, 131086, 262145, 18, 196622, 262145, 18, 262158, 262145, 18, 458754, 196609, 18, 393218, 196609, 18, 327682, 196609, 18, 327681, 196609, 18, 393217, 196609, 18, 458753, 196609, 18, 131075, 196609, 18, 65539, 196609, 18, 65538, 196609, 18, 65537, 196609, 18, 131073, 196609, 18, 131074, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_qk1jn")] -position = Vector2(160, 96) -toward_room_id = 3 +position = Vector2(112, 112) +toward_room_id = 7 [node name="stairs2" parent="." instance=ExtResource("3_qk1jn")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 8 diff --git a/src/maps/map-7.tscn b/src/maps/map-7.tscn index 07a8237..c35aed7 100644 --- a/src/maps/map-7.tscn +++ b/src/maps/map-7.tscn @@ -11,16 +11,12 @@ script = ExtResource("1_4rl4u") tile_set = ExtResource("2_hcug5") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 196609, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 262145, 262145, 18, 131075, 262145, 18, 196611, 262145, 18, 14, 1245185, 0, 13, 1245185, 0, 65550, 262145, 18, 131086, 262145, 18, 196622, 262145, 18, 393230, 262145, 18, 458766, 262145, 18, 458765, 262145, 18, 393228, 262145, 18, 393229, 262145, 18, 196621, 262145, 18, 131085, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 196618, 262145, 18, 458757, 262145, 18, 458758, 262145, 18, 458756, 196609, 18, 458755, 196609, 18, 458754, 196609, 18, 458753, 196609, 18, 327693, 196609, 18, 327694, 196609, 18, 262158, 196609, 18, 262157, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_3nspj")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_3nspj")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 3 diff --git a/src/maps/map-77.tscn b/src/maps/map-77.tscn index e1cc1c3..4c4df4b 100644 --- a/src/maps/map-77.tscn +++ b/src/maps/map-77.tscn @@ -11,16 +11,11 @@ script = ExtResource("1_f3vvj") tile_set = ExtResource("2_l7q50") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_les7w")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_les7w")] -position = Vector2(192, 48) -toward_room_id = 6 +position = Vector2(192, 64) +toward_room_id = 1 diff --git a/src/maps/map-8.tscn b/src/maps/map-8.tscn index 8cf74f6..d6cce5d 100644 --- a/src/maps/map-8.tscn +++ b/src/maps/map-8.tscn @@ -11,16 +11,12 @@ script = ExtResource("1_xna0b") tile_set = ExtResource("2_s8tme") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 393217, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 393221, 262145, 18, 393222, 262145, 18, 458758, 262145, 18, 458757, 262145, 18, 458756, 262145, 18, 458755, 262145, 18, 458754, 262145, 18, 458753, 262145, 18, 327687, 262145, 18, 262152, 262145, 18, 196617, 262145, 18, 131075, 196609, 18, 65539, 196609, 18, 65540, 196609, 18, 65541, 196609, 18, 65542, 196609, 18, 65543, 196609, 18, 65544, 196609, 18, 65545, 196609, 18, 65546, 196609, 18, 65547, 196609, 18, 131083, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_cycrh")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_cycrh")] -position = Vector2(192, 48) -toward_room_id = 6 +position = Vector2(96, 80) +toward_room_id = 10 diff --git a/src/maps/map-9.tscn b/src/maps/map-9.tscn index e0a21d2..2dd65db 100644 --- a/src/maps/map-9.tscn +++ b/src/maps/map-9.tscn @@ -11,16 +11,20 @@ script = ExtResource("1_ojfbm") tile_set = ExtResource("2_tet7f") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 524291, 1245185, 2, 196616, 262145, 18, 262152, 262145, 18, 327688, 262145, 18, 196611, 262145, 18, 262147, 262145, 18, 327683, 262145, 18, 393224, 196609, 18, 393219, 196609, 18, 131080, 196609, 18, 131075, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(160, 96) -toward_room_id = 3 +position = Vector2(197, 27) +toward_room_id = 1 [node name="stairs2" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(192, 48) +position = Vector2(197, 62) +toward_room_id = 3 + +[node name="stairs3" parent="." instance=ExtResource("3_n0dp0")] +position = Vector2(198, 108) toward_room_id = 6 From 10434847028e471c239b8780f9312a18a9c34105 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sun, 21 Apr 2024 10:53:45 -0400 Subject: [PATCH 79/86] cleaning up the codebase --- src/maps/map-4.tscn | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/maps/map-4.tscn diff --git a/src/maps/map-4.tscn b/src/maps/map-4.tscn deleted file mode 100644 index 9bd6d65..0000000 --- a/src/maps/map-4.tscn +++ /dev/null @@ -1,22 +0,0 @@ -[gd_scene load_steps=4 format=3 uid="uid://22clf0thbdqv"] - -[ext_resource type="Script" path="res://src/maps/map.gd" id="1_qwjcs"] -[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_1bcx7"] -[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_w7jut"] - -[node name="Map" type="Node2D"] -script = ExtResource("1_qwjcs") - -[node name="TileMap" type="TileMap" parent="."] -tile_set = ExtResource("2_1bcx7") -format = 2 -layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18) -layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) - -[node name="PlayerSpawn" type="Marker2D" parent="."] -position = Vector2(80, 48) - -[node name="stairs" parent="." instance=ExtResource("3_w7jut")] -position = Vector2(192, 64) -toward_room_id = 5 From 7455c0531d4b8b44b5670911fa6b6b7f49e2c8f3 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sun, 21 Apr 2024 19:41:38 -0400 Subject: [PATCH 80/86] re-wrote some functions --- .gitignore | 1 + src/boots/boots.gd | 8 ++++---- src/items/item_db.gd | 12 ++++++------ src/maps/map-1.tscn | 1 - src/maps/map-2.tscn | 1 - src/maps/map-3.tscn | 2 -- todo.md | 26 -------------------------- 7 files changed, 11 insertions(+), 40 deletions(-) delete mode 100644 todo.md diff --git a/.gitignore b/.gitignore index 7765de2..613493f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ addons/ .obsidian/ +todo.md \ No newline at end of file diff --git a/src/boots/boots.gd b/src/boots/boots.gd index 58f96e1..61e54e8 100644 --- a/src/boots/boots.gd +++ b/src/boots/boots.gd @@ -6,13 +6,13 @@ var teleport_move_code: Array[String] = ["down","up","down","up"] var recent_moves: Array[String] = ["","","","","",""] # Called when the node enters the scene tree for the first time. -signal teleport_requested() +signal teleport_entered() func _ready() -> void: print("BOOTS ON!!!") connect_to_player() connect_to_main() - + func connect_to_player() -> void: var player := get_parent() @@ -20,7 +20,7 @@ func connect_to_player() -> void: func connect_to_main() -> void: var main := get_parent().get_parent() - self.connect("teleport_requested", Callable(main, "on_teleport_requested")) + self.teleport_entered.connect(main.on_teleport_entered) func player_moved(dir: Vector2) -> void: match dir: @@ -46,7 +46,7 @@ func check_move_codes(): if recent_moves == winning_move_code: code_entered() if recent_moves.slice(1,-1) == teleport_move_code: - teleport_requested.emit() + teleport_entered.emit() pass pass diff --git a/src/items/item_db.gd b/src/items/item_db.gd index ae28209..5dfd793 100644 --- a/src/items/item_db.gd +++ b/src/items/item_db.gd @@ -27,12 +27,12 @@ func give_item(id:String) -> void: new_item.icon = load("res://assets/item_icons/" + icon_name) new_item.description = ITEMS[id]["description"] - # add resource to player inventory - var current_scene = _get_current_scene() - var player:Player = current_scene.get_node("Player") - #if player.has_item(new_item) == false or new_item["unique"] == false: - player.inventory.append(new_item) - print('player now has item: ', new_item.title) + # add resource to player inventory + var current_scene = _get_current_scene() + var player:Player = current_scene.get_node("Player") + #if player.has_item(new_item) == false or new_item["unique"] == false: + player.inventory.append(new_item) + print('player now has item: ', new_item.title) func _get_current_scene(): diff --git a/src/maps/map-1.tscn b/src/maps/map-1.tscn index 094cd6c..48c7873 100644 --- a/src/maps/map-1.tscn +++ b/src/maps/map-1.tscn @@ -19,4 +19,3 @@ position = Vector2(80, 48) [node name="stairs" parent="." instance=ExtResource("3_8x2ye")] position = Vector2(160, 96) -toward_room_id = 2 diff --git a/src/maps/map-2.tscn b/src/maps/map-2.tscn index a46ebf8..abaa883 100644 --- a/src/maps/map-2.tscn +++ b/src/maps/map-2.tscn @@ -19,4 +19,3 @@ position = Vector2(144, 48) [node name="stairs" parent="." instance=ExtResource("3_wvxh7")] position = Vector2(192, 80) -toward_room_id = 3 diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn index d68246d..4309492 100644 --- a/src/maps/map-3.tscn +++ b/src/maps/map-3.tscn @@ -19,8 +19,6 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_vucpd")] position = Vector2(160, 96) -toward_room_id = 4 [node name="stairs2" parent="." instance=ExtResource("3_vucpd")] position = Vector2(192, 48) -toward_room_id = 77 diff --git a/todo.md b/todo.md deleted file mode 100644 index ea01a5d..0000000 --- a/todo.md +++ /dev/null @@ -1,26 +0,0 @@ -# inventory -## inventory datatype: -- manages an Items Id, icon, description(s), and if the player has it or not? (should they manage that too?) -## inventory screen: -- lets you see all the items you currently have with descriptions of them, pressing action button lets you equip it. -## items in game: -- npcs can check your equipped item and special cutscenes can happen - -## format ideas: -### items are all scenes: -- no -### Items are all resources: -- give resources through their url -- would let us manage multiple instances of an item -- maybe the db could act as a master reference, the resource could act as instances? -### item db -- items are all in a big list, give them though id - - -# todo: -- clean things up -- update contribution instructions -- work on settings menu: - - control mapping? - - resolution scale, integer or fit - - \ No newline at end of file From 315fc585543a5e9da262fcc5f0f26b9aba6971d3 Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sun, 21 Apr 2024 19:46:21 -0400 Subject: [PATCH 81/86] no return value for teleport func --- src/main/main.gd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/main.gd b/src/main/main.gd index 2869c55..caa2367 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -26,6 +26,7 @@ func on_teleport_entered() -> void: match current_map_id: 77: print("can't teleport") + return 11: next_map_id = 2 10: @@ -42,6 +43,7 @@ func on_teleport_entered() -> void: if potential_tile != null: print("can't teleport") + return # go to new map current_map.queue_free() From 7286f7f89aedd14e6ac607bab2e1eee381e0d40d Mon Sep 17 00:00:00 2001 From: Tigran <122690491+TigranExe@users.noreply.github.com> Date: Sun, 21 Apr 2024 10:45:42 -0400 Subject: [PATCH 82/86] Teleportation And Preparing for next levels --- src/boots/boots.gd | 5 ++++- src/maps/map-10.tscn | 10 +++++++--- src/maps/map-11.tscn | 22 +++++++++++++--------- src/maps/map-2.tscn | 1 + src/maps/map-3.tscn | 4 +++- src/maps/map-5.tscn | 14 +++++++------- src/maps/map-6.tscn | 8 ++++---- src/maps/map-7.tscn | 8 ++++++-- src/maps/map-77.tscn | 9 +++++++-- src/maps/map-8.tscn | 10 +++++++--- src/maps/map-9.tscn | 12 ++++-------- 11 files changed, 63 insertions(+), 40 deletions(-) diff --git a/src/boots/boots.gd b/src/boots/boots.gd index 61e54e8..2532ddc 100644 --- a/src/boots/boots.gd +++ b/src/boots/boots.gd @@ -13,7 +13,6 @@ func _ready() -> void: connect_to_player() connect_to_main() - func connect_to_player() -> void: var player := get_parent() player.moved.connect(player_moved) @@ -46,7 +45,11 @@ func check_move_codes(): if recent_moves == winning_move_code: code_entered() if recent_moves.slice(1,-1) == teleport_move_code: +<<<<<<< HEAD teleport_entered.emit() +======= + teleport_requested.emit() +>>>>>>> 19aa049 (Teleportation And Preparing for next levels) pass pass diff --git a/src/maps/map-10.tscn b/src/maps/map-10.tscn index 2ccc5ed..cf7cc47 100644 --- a/src/maps/map-10.tscn +++ b/src/maps/map-10.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=4 format=3 uid="uid://behqbmue4bheh"] +[gd_scene load_steps=4 format=3 uid="uid://tbdug0eavdeu"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_0dl14"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_f1sjl"] @@ -11,7 +11,7 @@ script = ExtResource("1_0dl14") tile_set = ExtResource("2_f1sjl") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -19,4 +19,8 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_l62f8")] position = Vector2(160, 96) -toward_room_id = 11 +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_l62f8")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-11.tscn b/src/maps/map-11.tscn index b3d5e87..c98dc1a 100644 --- a/src/maps/map-11.tscn +++ b/src/maps/map-11.tscn @@ -1,22 +1,26 @@ -[gd_scene load_steps=4 format=3 uid="uid://tbdug0eavdeu"] +[gd_scene load_steps=4 format=3 uid="uid://behqbmue4bheh"] -[ext_resource type="Script" path="res://src/maps/map.gd" id="1_0dl14"] -[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_f1sjl"] -[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_l62f8"] +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_6lakl"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_l41to"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_1hxxh"] [node name="Map" type="Node2D"] -script = ExtResource("1_0dl14") +script = ExtResource("1_6lakl") [node name="TileMap" type="TileMap" parent="."] -tile_set = ExtResource("2_f1sjl") +tile_set = ExtResource("2_l41to") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524302, 1245185, 2, 524291, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 393218, 262145, 18, 327682, 262145, 18, 262146, 262145, 18, 196610, 262145, 18, 131074, 262145, 18, 393221, 262145, 18, 196613, 262145, 18, 131077, 262145, 18, 393224, 262145, 18, 327688, 262145, 18, 262152, 262145, 18, 196616, 262145, 18, 131080, 262145, 18, 393227, 262145, 18, 196619, 262145, 18, 131083, 262145, 18, 262155, 196609, 18, 327691, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) -[node name="stairs" parent="." instance=ExtResource("3_l62f8")] +[node name="stairs" parent="." instance=ExtResource("3_1hxxh")] +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_1hxxh")] position = Vector2(192, 48) -toward_room_id = 1 +toward_room_id = 6 diff --git a/src/maps/map-2.tscn b/src/maps/map-2.tscn index abaa883..a46ebf8 100644 --- a/src/maps/map-2.tscn +++ b/src/maps/map-2.tscn @@ -19,3 +19,4 @@ position = Vector2(144, 48) [node name="stairs" parent="." instance=ExtResource("3_wvxh7")] position = Vector2(192, 80) +toward_room_id = 3 diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn index 4309492..d09f580 100644 --- a/src/maps/map-3.tscn +++ b/src/maps/map-3.tscn @@ -11,7 +11,7 @@ script = ExtResource("1_kwl2f") tile_set = ExtResource("1_xfyi1") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 327690, 262145, 18, 262153, 262145, 18, 196616, 262145, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -19,6 +19,8 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_vucpd")] position = Vector2(160, 96) +toward_room_id = 1 [node name="stairs2" parent="." instance=ExtResource("3_vucpd")] position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-5.tscn b/src/maps/map-5.tscn index 0d0681b..633932b 100644 --- a/src/maps/map-5.tscn +++ b/src/maps/map-5.tscn @@ -1,9 +1,8 @@ -[gd_scene load_steps=5 format=3 uid="uid://cy6ft3gis6xo1"] +[gd_scene load_steps=4 format=3 uid="uid://cy6ft3gis6xo1"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_1iq0s"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_bw06a"] [ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_oj5pp"] -[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="4_wwsf8"] [node name="Map" type="Node2D"] script = ExtResource("1_1iq0s") @@ -12,15 +11,16 @@ script = ExtResource("1_1iq0s") tile_set = ExtResource("2_bw06a") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 458754, 262145, 18, 393218, 262145, 18, 327682, 262145, 18, 262146, 262145, 18, 196610, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 131075, 262145, 18, 131076, 262145, 18, 196614, 262145, 18, 262147, 262145, 18, 262148, 262145, 18, 196611, 262145, 18, 196615, 262145, 18, 196616, 262145, 18, 262153, 262145, 18, 327690, 262145, 18, 327691, 262145, 18, 196612, 196609, 18, 196613, 196609, 18, 131077, 196609, 18, 131078, 196609, 18, 131079, 196609, 18, 131080, 196609, 18, 131081, 196609, 18, 196617, 196609, 18, 327689, 262145, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_oj5pp")] -position = Vector2(112, 96) -toward_room_id = 6 +position = Vector2(160, 96) +toward_room_id = 3 -[node name="Chest" parent="." instance=ExtResource("4_wwsf8")] -position = Vector2(176, 48) +[node name="stairs2" parent="." instance=ExtResource("3_oj5pp")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-6.tscn b/src/maps/map-6.tscn index 467020e..e39a009 100644 --- a/src/maps/map-6.tscn +++ b/src/maps/map-6.tscn @@ -11,16 +11,16 @@ script = ExtResource("1_8dqx8") tile_set = ExtResource("2_iwcel") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 524291, 1245185, 2, 196615, 262145, 18, 196616, 262145, 18, 131079, 262145, 18, 65544, 262145, 18, 65543, 262145, 18, 131080, 262145, 18, 196617, 262145, 18, 65545, 262145, 18, 131081, 262145, 18, 131082, 262145, 18, 196618, 262145, 18, 65546, 262145, 18, 458766, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 393229, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393228, 262145, 18, 327693, 262145, 18, 458755, 262145, 18, 458756, 262145, 18, 393219, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 65549, 262145, 18, 65550, 262145, 18, 131086, 262145, 18, 196622, 262145, 18, 262158, 262145, 18, 458754, 196609, 18, 393218, 196609, 18, 327682, 196609, 18, 327681, 196609, 18, 393217, 196609, 18, 458753, 196609, 18, 131075, 196609, 18, 65539, 196609, 18, 65538, 196609, 18, 65537, 196609, 18, 131073, 196609, 18, 131074, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_qk1jn")] -position = Vector2(112, 112) -toward_room_id = 7 +position = Vector2(160, 96) +toward_room_id = 3 [node name="stairs2" parent="." instance=ExtResource("3_qk1jn")] position = Vector2(192, 48) -toward_room_id = 8 +toward_room_id = 6 diff --git a/src/maps/map-7.tscn b/src/maps/map-7.tscn index c35aed7..07a8237 100644 --- a/src/maps/map-7.tscn +++ b/src/maps/map-7.tscn @@ -11,12 +11,16 @@ script = ExtResource("1_4rl4u") tile_set = ExtResource("2_hcug5") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 196609, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 262145, 262145, 18, 131075, 262145, 18, 196611, 262145, 18, 14, 1245185, 0, 13, 1245185, 0, 65550, 262145, 18, 131086, 262145, 18, 196622, 262145, 18, 393230, 262145, 18, 458766, 262145, 18, 458765, 262145, 18, 393228, 262145, 18, 393229, 262145, 18, 196621, 262145, 18, 131085, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 196618, 262145, 18, 458757, 262145, 18, 458758, 262145, 18, 458756, 196609, 18, 458755, 196609, 18, 458754, 196609, 18, 458753, 196609, 18, 327693, 196609, 18, 327694, 196609, 18, 262158, 196609, 18, 262157, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_3nspj")] -position = Vector2(192, 48) +position = Vector2(160, 96) toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_3nspj")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-77.tscn b/src/maps/map-77.tscn index 4c4df4b..e1cc1c3 100644 --- a/src/maps/map-77.tscn +++ b/src/maps/map-77.tscn @@ -11,11 +11,16 @@ script = ExtResource("1_f3vvj") tile_set = ExtResource("2_l7q50") format = 2 layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_les7w")] -position = Vector2(192, 64) -toward_room_id = 1 +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_les7w")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-8.tscn b/src/maps/map-8.tscn index d6cce5d..8cf74f6 100644 --- a/src/maps/map-8.tscn +++ b/src/maps/map-8.tscn @@ -11,12 +11,16 @@ script = ExtResource("1_xna0b") tile_set = ExtResource("2_s8tme") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 393217, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 393221, 262145, 18, 393222, 262145, 18, 458758, 262145, 18, 458757, 262145, 18, 458756, 262145, 18, 458755, 262145, 18, 458754, 262145, 18, 458753, 262145, 18, 327687, 262145, 18, 262152, 262145, 18, 196617, 262145, 18, 131075, 196609, 18, 65539, 196609, 18, 65540, 196609, 18, 65541, 196609, 18, 65542, 196609, 18, 65543, 196609, 18, 65544, 196609, 18, 65545, 196609, 18, 65546, 196609, 18, 65547, 196609, 18, 131083, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_cycrh")] -position = Vector2(96, 80) -toward_room_id = 10 +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_cycrh")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-9.tscn b/src/maps/map-9.tscn index 2dd65db..e0a21d2 100644 --- a/src/maps/map-9.tscn +++ b/src/maps/map-9.tscn @@ -11,20 +11,16 @@ script = ExtResource("1_ojfbm") tile_set = ExtResource("2_tet7f") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 524291, 1245185, 2, 196616, 262145, 18, 262152, 262145, 18, 327688, 262145, 18, 196611, 262145, 18, 262147, 262145, 18, 327683, 262145, 18, 393224, 196609, 18, 393219, 196609, 18, 131080, 196609, 18, 131075, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(197, 27) -toward_room_id = 1 - -[node name="stairs2" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(197, 62) +position = Vector2(160, 96) toward_room_id = 3 -[node name="stairs3" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(198, 108) +[node name="stairs2" parent="." instance=ExtResource("3_n0dp0")] +position = Vector2(192, 48) toward_room_id = 6 From e76246aa099c3f43574fa1bddac51ed1275ac486 Mon Sep 17 00:00:00 2001 From: Tigran <122690491+TigranExe@users.noreply.github.com> Date: Sun, 21 Apr 2024 11:18:56 -0400 Subject: [PATCH 83/86] Map puzzles Now in! --- src/maps/map-1.tscn | 4 ++++ src/maps/map-10.tscn | 10 +++------- src/maps/map-11.tscn | 22 +++++++++------------- src/maps/map-3.tscn | 6 +++--- src/maps/map-4.tscn | 22 ++++++++++++++++++++++ src/maps/map-5.tscn | 14 +++++++------- src/maps/map-6.tscn | 8 ++++---- src/maps/map-7.tscn | 8 ++------ src/maps/map-77.tscn | 9 ++------- src/maps/map-8.tscn | 10 +++------- src/maps/map-9.tscn | 12 ++++++++---- 11 files changed, 67 insertions(+), 58 deletions(-) create mode 100644 src/maps/map-4.tscn diff --git a/src/maps/map-1.tscn b/src/maps/map-1.tscn index 48c7873..4d744d5 100644 --- a/src/maps/map-1.tscn +++ b/src/maps/map-1.tscn @@ -19,3 +19,7 @@ position = Vector2(80, 48) [node name="stairs" parent="." instance=ExtResource("3_8x2ye")] position = Vector2(160, 96) +<<<<<<< HEAD +======= +toward_room_id = 2 +>>>>>>> 19a3cf7 (Map puzzles Now in!) diff --git a/src/maps/map-10.tscn b/src/maps/map-10.tscn index cf7cc47..2ccc5ed 100644 --- a/src/maps/map-10.tscn +++ b/src/maps/map-10.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=4 format=3 uid="uid://tbdug0eavdeu"] +[gd_scene load_steps=4 format=3 uid="uid://behqbmue4bheh"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_0dl14"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_f1sjl"] @@ -11,7 +11,7 @@ script = ExtResource("1_0dl14") tile_set = ExtResource("2_f1sjl") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -19,8 +19,4 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_l62f8")] position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_l62f8")] -position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 11 diff --git a/src/maps/map-11.tscn b/src/maps/map-11.tscn index c98dc1a..b3d5e87 100644 --- a/src/maps/map-11.tscn +++ b/src/maps/map-11.tscn @@ -1,26 +1,22 @@ -[gd_scene load_steps=4 format=3 uid="uid://behqbmue4bheh"] +[gd_scene load_steps=4 format=3 uid="uid://tbdug0eavdeu"] -[ext_resource type="Script" path="res://src/maps/map.gd" id="1_6lakl"] -[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_l41to"] -[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_1hxxh"] +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_0dl14"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_f1sjl"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_l62f8"] [node name="Map" type="Node2D"] -script = ExtResource("1_6lakl") +script = ExtResource("1_0dl14") [node name="TileMap" type="TileMap" parent="."] -tile_set = ExtResource("2_l41to") +tile_set = ExtResource("2_f1sjl") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524302, 1245185, 2, 524291, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 393218, 262145, 18, 327682, 262145, 18, 262146, 262145, 18, 196610, 262145, 18, 131074, 262145, 18, 393221, 262145, 18, 196613, 262145, 18, 131077, 262145, 18, 393224, 262145, 18, 327688, 262145, 18, 262152, 262145, 18, 196616, 262145, 18, 131080, 262145, 18, 393227, 262145, 18, 196619, 262145, 18, 131083, 262145, 18, 262155, 196609, 18, 327691, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) -[node name="stairs" parent="." instance=ExtResource("3_1hxxh")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_1hxxh")] +[node name="stairs" parent="." instance=ExtResource("3_l62f8")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 1 diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn index d09f580..d68246d 100644 --- a/src/maps/map-3.tscn +++ b/src/maps/map-3.tscn @@ -11,7 +11,7 @@ script = ExtResource("1_kwl2f") tile_set = ExtResource("1_xfyi1") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 327690, 262145, 18, 262153, 262145, 18, 196616, 262145, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -19,8 +19,8 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_vucpd")] position = Vector2(160, 96) -toward_room_id = 1 +toward_room_id = 4 [node name="stairs2" parent="." instance=ExtResource("3_vucpd")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 77 diff --git a/src/maps/map-4.tscn b/src/maps/map-4.tscn new file mode 100644 index 0000000..9bd6d65 --- /dev/null +++ b/src/maps/map-4.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=4 format=3 uid="uid://22clf0thbdqv"] + +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_qwjcs"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_1bcx7"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_w7jut"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_qwjcs") + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("2_1bcx7") +format = 2 +layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524291, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65537, 262145, 18, 131073, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18) +layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) + +[node name="PlayerSpawn" type="Marker2D" parent="."] +position = Vector2(80, 48) + +[node name="stairs" parent="." instance=ExtResource("3_w7jut")] +position = Vector2(192, 64) +toward_room_id = 5 diff --git a/src/maps/map-5.tscn b/src/maps/map-5.tscn index 633932b..0d0681b 100644 --- a/src/maps/map-5.tscn +++ b/src/maps/map-5.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=4 format=3 uid="uid://cy6ft3gis6xo1"] +[gd_scene load_steps=5 format=3 uid="uid://cy6ft3gis6xo1"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_1iq0s"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_bw06a"] [ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_oj5pp"] +[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="4_wwsf8"] [node name="Map" type="Node2D"] script = ExtResource("1_1iq0s") @@ -11,16 +12,15 @@ script = ExtResource("1_1iq0s") tile_set = ExtResource("2_bw06a") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 458754, 262145, 18, 393218, 262145, 18, 327682, 262145, 18, 262146, 262145, 18, 196610, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 131075, 262145, 18, 131076, 262145, 18, 196614, 262145, 18, 262147, 262145, 18, 262148, 262145, 18, 196611, 262145, 18, 196615, 262145, 18, 196616, 262145, 18, 262153, 262145, 18, 327690, 262145, 18, 327691, 262145, 18, 196612, 196609, 18, 196613, 196609, 18, 131077, 196609, 18, 131078, 196609, 18, 131079, 196609, 18, 131080, 196609, 18, 131081, 196609, 18, 196617, 196609, 18, 327689, 262145, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_oj5pp")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_oj5pp")] -position = Vector2(192, 48) +position = Vector2(112, 96) toward_room_id = 6 + +[node name="Chest" parent="." instance=ExtResource("4_wwsf8")] +position = Vector2(176, 48) diff --git a/src/maps/map-6.tscn b/src/maps/map-6.tscn index e39a009..467020e 100644 --- a/src/maps/map-6.tscn +++ b/src/maps/map-6.tscn @@ -11,16 +11,16 @@ script = ExtResource("1_8dqx8") tile_set = ExtResource("2_iwcel") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 524291, 1245185, 2, 196615, 262145, 18, 196616, 262145, 18, 131079, 262145, 18, 65544, 262145, 18, 65543, 262145, 18, 131080, 262145, 18, 196617, 262145, 18, 65545, 262145, 18, 131081, 262145, 18, 131082, 262145, 18, 196618, 262145, 18, 65546, 262145, 18, 458766, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 393229, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393228, 262145, 18, 327693, 262145, 18, 458755, 262145, 18, 458756, 262145, 18, 393219, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 65549, 262145, 18, 65550, 262145, 18, 131086, 262145, 18, 196622, 262145, 18, 262158, 262145, 18, 458754, 196609, 18, 393218, 196609, 18, 327682, 196609, 18, 327681, 196609, 18, 393217, 196609, 18, 458753, 196609, 18, 131075, 196609, 18, 65539, 196609, 18, 65538, 196609, 18, 65537, 196609, 18, 131073, 196609, 18, 131074, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_qk1jn")] -position = Vector2(160, 96) -toward_room_id = 3 +position = Vector2(112, 112) +toward_room_id = 7 [node name="stairs2" parent="." instance=ExtResource("3_qk1jn")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 8 diff --git a/src/maps/map-7.tscn b/src/maps/map-7.tscn index 07a8237..c35aed7 100644 --- a/src/maps/map-7.tscn +++ b/src/maps/map-7.tscn @@ -11,16 +11,12 @@ script = ExtResource("1_4rl4u") tile_set = ExtResource("2_hcug5") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 196609, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 262145, 262145, 18, 131075, 262145, 18, 196611, 262145, 18, 14, 1245185, 0, 13, 1245185, 0, 65550, 262145, 18, 131086, 262145, 18, 196622, 262145, 18, 393230, 262145, 18, 458766, 262145, 18, 458765, 262145, 18, 393228, 262145, 18, 393229, 262145, 18, 196621, 262145, 18, 131085, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 196618, 262145, 18, 458757, 262145, 18, 458758, 262145, 18, 458756, 196609, 18, 458755, 196609, 18, 458754, 196609, 18, 458753, 196609, 18, 327693, 196609, 18, 327694, 196609, 18, 262158, 196609, 18, 262157, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_3nspj")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_3nspj")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 3 diff --git a/src/maps/map-77.tscn b/src/maps/map-77.tscn index e1cc1c3..4c4df4b 100644 --- a/src/maps/map-77.tscn +++ b/src/maps/map-77.tscn @@ -11,16 +11,11 @@ script = ExtResource("1_f3vvj") tile_set = ExtResource("2_l7q50") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_les7w")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_les7w")] -position = Vector2(192, 48) -toward_room_id = 6 +position = Vector2(192, 64) +toward_room_id = 1 diff --git a/src/maps/map-8.tscn b/src/maps/map-8.tscn index 8cf74f6..d6cce5d 100644 --- a/src/maps/map-8.tscn +++ b/src/maps/map-8.tscn @@ -11,16 +11,12 @@ script = ExtResource("1_xna0b") tile_set = ExtResource("2_s8tme") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 393217, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 393221, 262145, 18, 393222, 262145, 18, 458758, 262145, 18, 458757, 262145, 18, 458756, 262145, 18, 458755, 262145, 18, 458754, 262145, 18, 458753, 262145, 18, 327687, 262145, 18, 262152, 262145, 18, 196617, 262145, 18, 131075, 196609, 18, 65539, 196609, 18, 65540, 196609, 18, 65541, 196609, 18, 65542, 196609, 18, 65543, 196609, 18, 65544, 196609, 18, 65545, 196609, 18, 65546, 196609, 18, 65547, 196609, 18, 131083, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_cycrh")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_cycrh")] -position = Vector2(192, 48) -toward_room_id = 6 +position = Vector2(96, 80) +toward_room_id = 10 diff --git a/src/maps/map-9.tscn b/src/maps/map-9.tscn index e0a21d2..2dd65db 100644 --- a/src/maps/map-9.tscn +++ b/src/maps/map-9.tscn @@ -11,16 +11,20 @@ script = ExtResource("1_ojfbm") tile_set = ExtResource("2_tet7f") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 524291, 1245185, 2, 196616, 262145, 18, 262152, 262145, 18, 327688, 262145, 18, 196611, 262145, 18, 262147, 262145, 18, 327683, 262145, 18, 393224, 196609, 18, 393219, 196609, 18, 131080, 196609, 18, 131075, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(160, 96) -toward_room_id = 3 +position = Vector2(197, 27) +toward_room_id = 1 [node name="stairs2" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(192, 48) +position = Vector2(197, 62) +toward_room_id = 3 + +[node name="stairs3" parent="." instance=ExtResource("3_n0dp0")] +position = Vector2(198, 108) toward_room_id = 6 From f72eb34dc270b34fb4254815d25042befcc5418b Mon Sep 17 00:00:00 2001 From: JUB_Yoush <yoush1337@gmail.com> Date: Sun, 21 Apr 2024 10:53:45 -0400 Subject: [PATCH 84/86] cleaning up the codebase --- todo.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 todo.md diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..ea01a5d --- /dev/null +++ b/todo.md @@ -0,0 +1,26 @@ +# inventory +## inventory datatype: +- manages an Items Id, icon, description(s), and if the player has it or not? (should they manage that too?) +## inventory screen: +- lets you see all the items you currently have with descriptions of them, pressing action button lets you equip it. +## items in game: +- npcs can check your equipped item and special cutscenes can happen + +## format ideas: +### items are all scenes: +- no +### Items are all resources: +- give resources through their url +- would let us manage multiple instances of an item +- maybe the db could act as a master reference, the resource could act as instances? +### item db +- items are all in a big list, give them though id + + +# todo: +- clean things up +- update contribution instructions +- work on settings menu: + - control mapping? + - resolution scale, integer or fit + - \ No newline at end of file From e7e613ef7a075488c32efaea8f37f86498adfab0 Mon Sep 17 00:00:00 2001 From: Tigran <122690491+TigranExe@users.noreply.github.com> Date: Sun, 21 Apr 2024 10:45:42 -0400 Subject: [PATCH 85/86] Teleportation And Preparing for next levels --- src/main/main.gd | 3 +++ src/maps/map-10.tscn | 10 +++++++--- src/maps/map-11.tscn | 22 +++++++++++++--------- src/maps/map-3.tscn | 4 ++-- src/maps/map-5.tscn | 14 +++++++------- src/maps/map-6.tscn | 8 ++++---- src/maps/map-7.tscn | 8 ++++++-- src/maps/map-77.tscn | 6 ++++++ src/maps/map-8.tscn | 10 +++++++--- src/maps/map-9.tscn | 12 ++++-------- 10 files changed, 59 insertions(+), 38 deletions(-) diff --git a/src/main/main.gd b/src/main/main.gd index caa2367..ac69036 100644 --- a/src/main/main.gd +++ b/src/main/main.gd @@ -43,7 +43,10 @@ func on_teleport_entered() -> void: if potential_tile != null: print("can't teleport") +<<<<<<< HEAD return +======= +>>>>>>> 4d938ce (Teleportation And Preparing for next levels) # go to new map current_map.queue_free() diff --git a/src/maps/map-10.tscn b/src/maps/map-10.tscn index 2ccc5ed..cf7cc47 100644 --- a/src/maps/map-10.tscn +++ b/src/maps/map-10.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=4 format=3 uid="uid://behqbmue4bheh"] +[gd_scene load_steps=4 format=3 uid="uid://tbdug0eavdeu"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_0dl14"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_f1sjl"] @@ -11,7 +11,7 @@ script = ExtResource("1_0dl14") tile_set = ExtResource("2_f1sjl") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -19,4 +19,8 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_l62f8")] position = Vector2(160, 96) -toward_room_id = 11 +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_l62f8")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-11.tscn b/src/maps/map-11.tscn index b3d5e87..c98dc1a 100644 --- a/src/maps/map-11.tscn +++ b/src/maps/map-11.tscn @@ -1,22 +1,26 @@ -[gd_scene load_steps=4 format=3 uid="uid://tbdug0eavdeu"] +[gd_scene load_steps=4 format=3 uid="uid://behqbmue4bheh"] -[ext_resource type="Script" path="res://src/maps/map.gd" id="1_0dl14"] -[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_f1sjl"] -[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_l62f8"] +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_6lakl"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_l41to"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_1hxxh"] [node name="Map" type="Node2D"] -script = ExtResource("1_0dl14") +script = ExtResource("1_6lakl") [node name="TileMap" type="TileMap" parent="."] -tile_set = ExtResource("2_f1sjl") +tile_set = ExtResource("2_l41to") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524302, 1245185, 2, 524291, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 393218, 262145, 18, 327682, 262145, 18, 262146, 262145, 18, 196610, 262145, 18, 131074, 262145, 18, 393221, 262145, 18, 196613, 262145, 18, 131077, 262145, 18, 393224, 262145, 18, 327688, 262145, 18, 262152, 262145, 18, 196616, 262145, 18, 131080, 262145, 18, 393227, 262145, 18, 196619, 262145, 18, 131083, 262145, 18, 262155, 196609, 18, 327691, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) -[node name="stairs" parent="." instance=ExtResource("3_l62f8")] +[node name="stairs" parent="." instance=ExtResource("3_1hxxh")] +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_1hxxh")] position = Vector2(192, 48) -toward_room_id = 1 +toward_room_id = 6 diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn index d68246d..ef88c1e 100644 --- a/src/maps/map-3.tscn +++ b/src/maps/map-3.tscn @@ -19,8 +19,8 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_vucpd")] position = Vector2(160, 96) -toward_room_id = 4 +toward_room_id = 1 [node name="stairs2" parent="." instance=ExtResource("3_vucpd")] position = Vector2(192, 48) -toward_room_id = 77 +toward_room_id = 6 diff --git a/src/maps/map-5.tscn b/src/maps/map-5.tscn index 0d0681b..633932b 100644 --- a/src/maps/map-5.tscn +++ b/src/maps/map-5.tscn @@ -1,9 +1,8 @@ -[gd_scene load_steps=5 format=3 uid="uid://cy6ft3gis6xo1"] +[gd_scene load_steps=4 format=3 uid="uid://cy6ft3gis6xo1"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_1iq0s"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_bw06a"] [ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_oj5pp"] -[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="4_wwsf8"] [node name="Map" type="Node2D"] script = ExtResource("1_1iq0s") @@ -12,15 +11,16 @@ script = ExtResource("1_1iq0s") tile_set = ExtResource("2_bw06a") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 458754, 262145, 18, 393218, 262145, 18, 327682, 262145, 18, 262146, 262145, 18, 196610, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 131075, 262145, 18, 131076, 262145, 18, 196614, 262145, 18, 262147, 262145, 18, 262148, 262145, 18, 196611, 262145, 18, 196615, 262145, 18, 196616, 262145, 18, 262153, 262145, 18, 327690, 262145, 18, 327691, 262145, 18, 196612, 196609, 18, 196613, 196609, 18, 131077, 196609, 18, 131078, 196609, 18, 131079, 196609, 18, 131080, 196609, 18, 131081, 196609, 18, 196617, 196609, 18, 327689, 262145, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_oj5pp")] -position = Vector2(112, 96) -toward_room_id = 6 +position = Vector2(160, 96) +toward_room_id = 3 -[node name="Chest" parent="." instance=ExtResource("4_wwsf8")] -position = Vector2(176, 48) +[node name="stairs2" parent="." instance=ExtResource("3_oj5pp")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-6.tscn b/src/maps/map-6.tscn index 467020e..e39a009 100644 --- a/src/maps/map-6.tscn +++ b/src/maps/map-6.tscn @@ -11,16 +11,16 @@ script = ExtResource("1_8dqx8") tile_set = ExtResource("2_iwcel") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 524291, 1245185, 2, 196615, 262145, 18, 196616, 262145, 18, 131079, 262145, 18, 65544, 262145, 18, 65543, 262145, 18, 131080, 262145, 18, 196617, 262145, 18, 65545, 262145, 18, 131081, 262145, 18, 131082, 262145, 18, 196618, 262145, 18, 65546, 262145, 18, 458766, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 393229, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393228, 262145, 18, 327693, 262145, 18, 458755, 262145, 18, 458756, 262145, 18, 393219, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 65549, 262145, 18, 65550, 262145, 18, 131086, 262145, 18, 196622, 262145, 18, 262158, 262145, 18, 458754, 196609, 18, 393218, 196609, 18, 327682, 196609, 18, 327681, 196609, 18, 393217, 196609, 18, 458753, 196609, 18, 131075, 196609, 18, 65539, 196609, 18, 65538, 196609, 18, 65537, 196609, 18, 131073, 196609, 18, 131074, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_qk1jn")] -position = Vector2(112, 112) -toward_room_id = 7 +position = Vector2(160, 96) +toward_room_id = 3 [node name="stairs2" parent="." instance=ExtResource("3_qk1jn")] position = Vector2(192, 48) -toward_room_id = 8 +toward_room_id = 6 diff --git a/src/maps/map-7.tscn b/src/maps/map-7.tscn index c35aed7..07a8237 100644 --- a/src/maps/map-7.tscn +++ b/src/maps/map-7.tscn @@ -11,12 +11,16 @@ script = ExtResource("1_4rl4u") tile_set = ExtResource("2_hcug5") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 196609, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 262145, 262145, 18, 131075, 262145, 18, 196611, 262145, 18, 14, 1245185, 0, 13, 1245185, 0, 65550, 262145, 18, 131086, 262145, 18, 196622, 262145, 18, 393230, 262145, 18, 458766, 262145, 18, 458765, 262145, 18, 393228, 262145, 18, 393229, 262145, 18, 196621, 262145, 18, 131085, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 196618, 262145, 18, 458757, 262145, 18, 458758, 262145, 18, 458756, 196609, 18, 458755, 196609, 18, 458754, 196609, 18, 458753, 196609, 18, 327693, 196609, 18, 327694, 196609, 18, 262158, 196609, 18, 262157, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_3nspj")] -position = Vector2(192, 48) +position = Vector2(160, 96) toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_3nspj")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-77.tscn b/src/maps/map-77.tscn index 4c4df4b..bce9fd1 100644 --- a/src/maps/map-77.tscn +++ b/src/maps/map-77.tscn @@ -11,11 +11,17 @@ script = ExtResource("1_f3vvj") tile_set = ExtResource("2_l7q50") format = 2 layer_0/name = "walls" +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_les7w")] +<<<<<<< HEAD position = Vector2(192, 64) toward_room_id = 1 +[node name="stairs2" parent="." instance=ExtResource("3_les7w")] +position = Vector2(192, 48) +toward_room_id = 6 +>>>>>>> bf0c3ce (Teleportation And Preparing for next levels) diff --git a/src/maps/map-8.tscn b/src/maps/map-8.tscn index d6cce5d..8cf74f6 100644 --- a/src/maps/map-8.tscn +++ b/src/maps/map-8.tscn @@ -11,12 +11,16 @@ script = ExtResource("1_xna0b") tile_set = ExtResource("2_s8tme") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 393217, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 393221, 262145, 18, 393222, 262145, 18, 458758, 262145, 18, 458757, 262145, 18, 458756, 262145, 18, 458755, 262145, 18, 458754, 262145, 18, 458753, 262145, 18, 327687, 262145, 18, 262152, 262145, 18, 196617, 262145, 18, 131075, 196609, 18, 65539, 196609, 18, 65540, 196609, 18, 65541, 196609, 18, 65542, 196609, 18, 65543, 196609, 18, 65544, 196609, 18, 65545, 196609, 18, 65546, 196609, 18, 65547, 196609, 18, 131083, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_cycrh")] -position = Vector2(96, 80) -toward_room_id = 10 +position = Vector2(160, 96) +toward_room_id = 3 + +[node name="stairs2" parent="." instance=ExtResource("3_cycrh")] +position = Vector2(192, 48) +toward_room_id = 6 diff --git a/src/maps/map-9.tscn b/src/maps/map-9.tscn index 2dd65db..e0a21d2 100644 --- a/src/maps/map-9.tscn +++ b/src/maps/map-9.tscn @@ -11,20 +11,16 @@ script = ExtResource("1_ojfbm") tile_set = ExtResource("2_tet7f") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 524291, 1245185, 2, 196616, 262145, 18, 262152, 262145, 18, 327688, 262145, 18, 196611, 262145, 18, 262147, 262145, 18, 327683, 262145, 18, 393224, 196609, 18, 393219, 196609, 18, 131080, 196609, 18, 131075, 196609, 18) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(197, 27) -toward_room_id = 1 - -[node name="stairs2" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(197, 62) +position = Vector2(160, 96) toward_room_id = 3 -[node name="stairs3" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(198, 108) +[node name="stairs2" parent="." instance=ExtResource("3_n0dp0")] +position = Vector2(192, 48) toward_room_id = 6 From 7fe45ecaf8ec87d232d7b26f888ae9df7242e2ca Mon Sep 17 00:00:00 2001 From: Tigran <122690491+TigranExe@users.noreply.github.com> Date: Sun, 21 Apr 2024 11:18:56 -0400 Subject: [PATCH 86/86] Map puzzles Now in! --- src/maps/map-10.tscn | 10 +++------- src/maps/map-11.tscn | 22 +++++++++------------- src/maps/map-3.tscn | 4 ++-- src/maps/map-5.tscn | 14 +++++++------- src/maps/map-6.tscn | 8 ++++---- src/maps/map-7.tscn | 8 ++------ src/maps/map-77.tscn | 3 --- src/maps/map-8.tscn | 10 +++------- src/maps/map-9.tscn | 12 ++++++++---- 9 files changed, 38 insertions(+), 53 deletions(-) diff --git a/src/maps/map-10.tscn b/src/maps/map-10.tscn index cf7cc47..2ccc5ed 100644 --- a/src/maps/map-10.tscn +++ b/src/maps/map-10.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=4 format=3 uid="uid://tbdug0eavdeu"] +[gd_scene load_steps=4 format=3 uid="uid://behqbmue4bheh"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_0dl14"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_f1sjl"] @@ -11,7 +11,7 @@ script = ExtResource("1_0dl14") tile_set = ExtResource("2_f1sjl") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] @@ -19,8 +19,4 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_l62f8")] position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_l62f8")] -position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 11 diff --git a/src/maps/map-11.tscn b/src/maps/map-11.tscn index c98dc1a..b3d5e87 100644 --- a/src/maps/map-11.tscn +++ b/src/maps/map-11.tscn @@ -1,26 +1,22 @@ -[gd_scene load_steps=4 format=3 uid="uid://behqbmue4bheh"] +[gd_scene load_steps=4 format=3 uid="uid://tbdug0eavdeu"] -[ext_resource type="Script" path="res://src/maps/map.gd" id="1_6lakl"] -[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_l41to"] -[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_1hxxh"] +[ext_resource type="Script" path="res://src/maps/map.gd" id="1_0dl14"] +[ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_f1sjl"] +[ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_l62f8"] [node name="Map" type="Node2D"] -script = ExtResource("1_6lakl") +script = ExtResource("1_0dl14") [node name="TileMap" type="TileMap" parent="."] -tile_set = ExtResource("2_l41to") +tile_set = ExtResource("2_f1sjl") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524302, 1245185, 2, 524291, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 393218, 262145, 18, 327682, 262145, 18, 262146, 262145, 18, 196610, 262145, 18, 131074, 262145, 18, 393221, 262145, 18, 196613, 262145, 18, 131077, 262145, 18, 393224, 262145, 18, 327688, 262145, 18, 262152, 262145, 18, 196616, 262145, 18, 131080, 262145, 18, 393227, 262145, 18, 196619, 262145, 18, 131083, 262145, 18, 262155, 196609, 18, 327691, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) -[node name="stairs" parent="." instance=ExtResource("3_1hxxh")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_1hxxh")] +[node name="stairs" parent="." instance=ExtResource("3_l62f8")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 1 diff --git a/src/maps/map-3.tscn b/src/maps/map-3.tscn index ef88c1e..d68246d 100644 --- a/src/maps/map-3.tscn +++ b/src/maps/map-3.tscn @@ -19,8 +19,8 @@ position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_vucpd")] position = Vector2(160, 96) -toward_room_id = 1 +toward_room_id = 4 [node name="stairs2" parent="." instance=ExtResource("3_vucpd")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 77 diff --git a/src/maps/map-5.tscn b/src/maps/map-5.tscn index 633932b..0d0681b 100644 --- a/src/maps/map-5.tscn +++ b/src/maps/map-5.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=4 format=3 uid="uid://cy6ft3gis6xo1"] +[gd_scene load_steps=5 format=3 uid="uid://cy6ft3gis6xo1"] [ext_resource type="Script" path="res://src/maps/map.gd" id="1_1iq0s"] [ext_resource type="TileSet" uid="uid://dmwbt07hsdtyl" path="res://src/resources/map_tileset.tres" id="2_bw06a"] [ext_resource type="PackedScene" uid="uid://cmdlpc0uddsm2" path="res://src/scene-tiles/stairs/stairs.tscn" id="3_oj5pp"] +[ext_resource type="PackedScene" uid="uid://cojb8qcua33fo" path="res://src/scene-tiles/chest/chest.tscn" id="4_wwsf8"] [node name="Map" type="Node2D"] script = ExtResource("1_1iq0s") @@ -11,16 +12,15 @@ script = ExtResource("1_1iq0s") tile_set = ExtResource("2_bw06a") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 458754, 262145, 18, 393218, 262145, 18, 327682, 262145, 18, 262146, 262145, 18, 196610, 262145, 18, 196609, 262145, 18, 262145, 262145, 18, 327681, 262145, 18, 393217, 262145, 18, 458753, 262145, 18, 131075, 262145, 18, 131076, 262145, 18, 196614, 262145, 18, 262147, 262145, 18, 262148, 262145, 18, 196611, 262145, 18, 196615, 262145, 18, 196616, 262145, 18, 262153, 262145, 18, 327690, 262145, 18, 327691, 262145, 18, 196612, 196609, 18, 196613, 196609, 18, 131077, 196609, 18, 131078, 196609, 18, 131079, 196609, 18, 131080, 196609, 18, 131081, 196609, 18, 196617, 196609, 18, 327689, 262145, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_oj5pp")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_oj5pp")] -position = Vector2(192, 48) +position = Vector2(112, 96) toward_room_id = 6 + +[node name="Chest" parent="." instance=ExtResource("4_wwsf8")] +position = Vector2(176, 48) diff --git a/src/maps/map-6.tscn b/src/maps/map-6.tscn index e39a009..467020e 100644 --- a/src/maps/map-6.tscn +++ b/src/maps/map-6.tscn @@ -11,16 +11,16 @@ script = ExtResource("1_8dqx8") tile_set = ExtResource("2_iwcel") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 524291, 1245185, 2, 196615, 262145, 18, 196616, 262145, 18, 131079, 262145, 18, 65544, 262145, 18, 65543, 262145, 18, 131080, 262145, 18, 196617, 262145, 18, 65545, 262145, 18, 131081, 262145, 18, 131082, 262145, 18, 196618, 262145, 18, 65546, 262145, 18, 458766, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 393229, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393228, 262145, 18, 327693, 262145, 18, 458755, 262145, 18, 458756, 262145, 18, 393219, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 65549, 262145, 18, 65550, 262145, 18, 131086, 262145, 18, 196622, 262145, 18, 262158, 262145, 18, 458754, 196609, 18, 393218, 196609, 18, 327682, 196609, 18, 327681, 196609, 18, 393217, 196609, 18, 458753, 196609, 18, 131075, 196609, 18, 65539, 196609, 18, 65538, 196609, 18, 65537, 196609, 18, 131073, 196609, 18, 131074, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_qk1jn")] -position = Vector2(160, 96) -toward_room_id = 3 +position = Vector2(112, 112) +toward_room_id = 7 [node name="stairs2" parent="." instance=ExtResource("3_qk1jn")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 8 diff --git a/src/maps/map-7.tscn b/src/maps/map-7.tscn index 07a8237..c35aed7 100644 --- a/src/maps/map-7.tscn +++ b/src/maps/map-7.tscn @@ -11,16 +11,12 @@ script = ExtResource("1_4rl4u") tile_set = ExtResource("2_hcug5") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 196609, 262145, 18, 196610, 262145, 18, 262146, 262145, 18, 262145, 262145, 18, 131075, 262145, 18, 196611, 262145, 18, 14, 1245185, 0, 13, 1245185, 0, 65550, 262145, 18, 131086, 262145, 18, 196622, 262145, 18, 393230, 262145, 18, 458766, 262145, 18, 458765, 262145, 18, 393228, 262145, 18, 393229, 262145, 18, 196621, 262145, 18, 131085, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 196618, 262145, 18, 458757, 262145, 18, 458758, 262145, 18, 458756, 196609, 18, 458755, 196609, 18, 458754, 196609, 18, 458753, 196609, 18, 327693, 196609, 18, 327694, 196609, 18, 262158, 196609, 18, 262157, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_3nspj")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_3nspj")] position = Vector2(192, 48) -toward_room_id = 6 +toward_room_id = 3 diff --git a/src/maps/map-77.tscn b/src/maps/map-77.tscn index bce9fd1..12ace6b 100644 --- a/src/maps/map-77.tscn +++ b/src/maps/map-77.tscn @@ -11,17 +11,14 @@ script = ExtResource("1_f3vvj") tile_set = ExtResource("2_l7q50") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_les7w")] -<<<<<<< HEAD position = Vector2(192, 64) toward_room_id = 1 [node name="stairs2" parent="." instance=ExtResource("3_les7w")] position = Vector2(192, 48) toward_room_id = 6 ->>>>>>> bf0c3ce (Teleportation And Preparing for next levels) diff --git a/src/maps/map-8.tscn b/src/maps/map-8.tscn index 8cf74f6..d6cce5d 100644 --- a/src/maps/map-8.tscn +++ b/src/maps/map-8.tscn @@ -11,16 +11,12 @@ script = ExtResource("1_xna0b") tile_set = ExtResource("2_s8tme") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131074, 262145, 18, 524291, 1245185, 2, 393217, 262145, 18, 393218, 262145, 18, 393219, 262145, 18, 393220, 262145, 18, 393221, 262145, 18, 393222, 262145, 18, 458758, 262145, 18, 458757, 262145, 18, 458756, 262145, 18, 458755, 262145, 18, 458754, 262145, 18, 458753, 262145, 18, 327687, 262145, 18, 262152, 262145, 18, 196617, 262145, 18, 131075, 196609, 18, 65539, 196609, 18, 65540, 196609, 18, 65541, 196609, 18, 65542, 196609, 18, 65543, 196609, 18, 65544, 196609, 18, 65545, 196609, 18, 65546, 196609, 18, 65547, 196609, 18, 131083, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_cycrh")] -position = Vector2(160, 96) -toward_room_id = 3 - -[node name="stairs2" parent="." instance=ExtResource("3_cycrh")] -position = Vector2(192, 48) -toward_room_id = 6 +position = Vector2(96, 80) +toward_room_id = 10 diff --git a/src/maps/map-9.tscn b/src/maps/map-9.tscn index e0a21d2..2dd65db 100644 --- a/src/maps/map-9.tscn +++ b/src/maps/map-9.tscn @@ -11,16 +11,20 @@ script = ExtResource("1_ojfbm") tile_set = ExtResource("2_tet7f") format = 2 layer_0/name = "walls" -layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 458766, 262145, 18, 458765, 262145, 18, 458764, 262145, 18, 458763, 262145, 18, 393230, 262145, 18, 327694, 262145, 18, 262158, 262145, 18, 196622, 262145, 18, 196621, 262145, 18, 262157, 262145, 18, 327693, 262145, 18, 393229, 262145, 18, 393228, 262145, 18, 327692, 262145, 18, 262156, 262145, 18, 393227, 262145, 18, 458762, 262145, 18, 458761, 262145, 18, 131086, 262145, 18, 65550, 262145, 18, 65549, 262145, 18, 131085, 262145, 18, 131073, 262145, 18, 65537, 262145, 18, 65538, 262145, 18, 65539, 262145, 18, 65540, 262145, 18, 65541, 262145, 18, 65542, 262145, 18, 65543, 262145, 18, 65544, 262145, 18, 65545, 262145, 18, 65546, 262145, 18, 65547, 262145, 18, 65548, 262145, 18, 131084, 262145, 18, 131083, 262145, 18, 131082, 262145, 18, 131081, 262145, 18, 131080, 262145, 18, 131079, 262145, 18, 131078, 262145, 18, 131077, 262145, 18, 131076, 262145, 18, 131075, 262145, 18, 131074, 262145, 18, 327690, 196609, 18, 262153, 196609, 18, 196616, 196609, 18, 524291, 1245185, 2) +layer_0/tile_data = PackedInt32Array(0, 1179649, 0, 1, 1245185, 0, 2, 1245185, 0, 3, 1245185, 0, 4, 1245185, 0, 5, 1245185, 0, 6, 1245185, 0, 7, 1245185, 0, 8, 1245185, 0, 9, 1245185, 0, 10, 1245185, 0, 65536, 1179649, 1, 131072, 1179649, 1, 196608, 1179649, 1, 262144, 1179649, 1, 327680, 1179649, 1, 393216, 1179649, 1, 458752, 1179649, 1, 524288, 1179649, 2, 11, 1245185, 0, 12, 1245185, 0, 13, 1245185, 0, 14, 1245185, 0, 15, 1310721, 0, 65551, 1310721, 1, 131087, 1310721, 1, 196623, 1310721, 1, 262159, 1310721, 1, 327695, 1310721, 1, 393231, 1310721, 1, 458767, 1310721, 1, 524303, 1310721, 2, 524289, 1245185, 2, 524290, 1245185, 2, 524292, 1245185, 2, 524293, 1245185, 2, 524294, 1245185, 2, 524295, 1245185, 2, 524296, 1245185, 2, 524297, 1245185, 2, 524298, 1245185, 2, 524299, 1245185, 2, 524300, 1245185, 2, 524301, 1245185, 2, 524302, 1245185, 2, 524291, 1245185, 2, 196616, 262145, 18, 262152, 262145, 18, 327688, 262145, 18, 196611, 262145, 18, 262147, 262145, 18, 327683, 262145, 18, 393224, 196609, 18, 393219, 196609, 18, 131080, 196609, 18, 131075, 196609, 18) layer_1/tile_data = PackedInt32Array(196615, 3, 65536, 393226, 3, 131072) [node name="PlayerSpawn" type="Marker2D" parent="."] position = Vector2(80, 64) [node name="stairs" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(160, 96) -toward_room_id = 3 +position = Vector2(197, 27) +toward_room_id = 1 [node name="stairs2" parent="." instance=ExtResource("3_n0dp0")] -position = Vector2(192, 48) +position = Vector2(197, 62) +toward_room_id = 3 + +[node name="stairs3" parent="." instance=ExtResource("3_n0dp0")] +position = Vector2(198, 108) toward_room_id = 6