diff --git a/_game/LevelDemonstration.tscn b/_game/LevelDemonstration.tscn new file mode 100644 index 0000000..524c5ad --- /dev/null +++ b/_game/LevelDemonstration.tscn @@ -0,0 +1,72 @@ +[gd_scene load_steps=12 format=4 uid="uid://bj2318o3y68x2"] + +[ext_resource type="PackedScene" uid="uid://1l06de041i40" path="res://_levels/l_level_1.tscn" id="1_p0ota"] +[ext_resource type="PackedScene" uid="uid://cvqehvdjpoar4" path="res://_player/player_controller.tscn" id="2_gslp7"] +[ext_resource type="PackedScene" uid="uid://gwhff4qaouxy" path="res://_player/Avatar.tscn" id="3_6jw57"] +[ext_resource type="PackedScene" uid="uid://b5nx4dntm0gyn" path="res://_props/door_manager/event_trigger_door.tscn" id="4_p0ota"] +[ext_resource type="Script" uid="uid://b4menkyub4ce7" path="res://addons/reedscene/prop/PropComponent.gd" id="5_gslp7"] +[ext_resource type="Script" uid="uid://7lml6d1t5xtq" path="res://addons/reedscene/prop/PropState.gd" id="6_6jw57"] +[ext_resource type="Script" uid="uid://cdvgq0xqdbagk" path="res://addons/reedscene/prop/ReedPropEffect.gd" id="7_2t6pm"] +[ext_resource type="Script" uid="uid://jeybblac0kg2" path="res://addons/reedscene/prop/ReedTransition.gd" id="8_xkd7q"] + +[sub_resource type="Resource" id="Resource_2t6pm"] +script = ExtResource("7_2t6pm") +effect_type = 1 +value = null +func_name = &"reset_door_state_id" +func_args = [0] +metadata/_custom_type_script = "uid://cdvgq0xqdbagk" + +[sub_resource type="Resource" id="Resource_g37lb"] +script = ExtResource("7_2t6pm") +effect_type = 1 +value = null +func_name = &"reset_door_state_id" +func_args = [1] +metadata/_custom_type_script = "uid://cdvgq0xqdbagk" + +[sub_resource type="Resource" id="Resource_xkd7q"] +script = ExtResource("7_2t6pm") +effect_type = 1 +value = null +func_name = &"door_open" +metadata/_custom_type_script = "uid://cdvgq0xqdbagk" + +[node name="Game" type="Node2D"] + +[node name="level_1" parent="." instance=ExtResource("1_p0ota")] +tile_map_data = PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAA4AAAAAAAAAAAAAAA8AAAAAAAAAAAAAABAAAAAAAAAAAAAAABEAAAAAAAAAAAAAABIAAAAAAAAAAAAAABMAAAAAAAAAAAAAABQAAAAAAAAAAAAAABUAAAAAAAAAAAAAABYAAAAAAAAAAAABAAAAAAAAAAAAAAABAAEAAAAAAAAAAAABAAIAAAAAAAAAAAABAAMAAAAAAAAAAAABAAQAAAAAAAAAAAABAAUAAAAAAAAAAAABAAYAAAAAAAAAAAABAAcAAAAAAAAAAAABAAgAAAAAAAAAAAABAAkAAAAAAAAAAAABAAoAAAAAAAAAAAABAAsAAAAAAAAAAAABAAwAAAAAAAAAAAABAA0AAAAAAAAAAAABAA4AAAAAAAAAAAABAA8AAAAAAAAAAAABABAAAAAAAAAAAAABABEAAAAAAAAAAAABABIAAAAAAAAAAAABABMAAAAAAAAAAAABABQAAAAAAAAAAAABABUAAAAAAAAAAAABABYAAAAAAAAAAAACAAAAAAAAAAAAAAACAAEAAAAAAAAAAAACAAIAAAAAAAAAAAACAAMAAAAAAAAAAAACAAQAAAAAAAAAAAACAAUAAAAAAAAAAAACAAYAAAAAAAAAAAACAAcAAAAAAAAAAAACAAgAAAAAAAAAAAACAAkAAAAAAAAAAAACAAoAAAAAAAAAAAACAAsAAAAAAAAAAAACAAwAAAAAAAAAAAACAA0AAAAAAAAAAAACAA4AAAAAAAAAAAACAA8AAAAAAAAAAAACABAAAAAAAAAAAAACABEAAAAAAAAAAAACABIAAAAAAAAAAAACABMAAAAAAAAAAAACABQAAAAAAAAAAAACABUAAAAAAAAAAAACABYAAAAAAAAAAAADAAAAAAAAAAAAAAADAAEAAAAAAAAAAAADAAIAAAAAAAAAAAADAAMAAAAAAAAAAAADAAQAAAAAAAAAAAADAAUAAAAAAAAAAAADAAYAAAAAAAAAAAADAAcAAAAAAAAAAAADAAgAAAAAAAAAAAADAAkAAAAAAAAAAAADAAoAAAAAAAAAAAADAAsAAAAAAAAAAAADAAwAAAAAAAAAAAADAA0AAAAAAAAAAAADAA4AAAAAAAAAAAADAA8AAAAAAAAAAAADABAAAAAAAAAAAAADABEAAAAAAAAAAAADABIAAAAAAAAAAAADABMAAAAAAAAAAAADABQAAAAAAAAAAAADABUAAAAAAAAAAAADABYAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAEAAAAAAAAAAAAEAAIAAAAAAAAAAAAEAAMAAAAAAAAAAAAEAAQAAAAAAAAAAAAEAAUAAAAAAAAAAAAEAAYAAAAAAAAAAAAEAAcAAAAAAAAAAAAEAAgAAAAAAAAAAAAEAAkAAAAAAAAAAAAEAAoAAAAAAAAAAAAEAAsAAAAAAAAAAAAEAAwAAAAAAAAAAAAEAA0AAAAAAAAAAAAEAA4AAAAAAAAAAAAEAA8AAAAAAAAAAAAEABAAAAAAAAAAAAAEABEAAAAAAAAAAAAEABIAAAAAAAAAAAAEABMAAAAAAAAAAAAEABQAAAAAAAAAAAAEABUAAAAAAAAAAAAEABYAAAAAAAAAAAAFAAAAAAAAAAAAAAAFAAEAAAAAAAAAAAAFAAIAAAAAAAAAAAAFAAMAAAAAAAAAAAAFAAQAAAAAAAAAAAAFAAUAAAAAAAAAAAAFAAYAAAAAAAAAAAAFAAcAAAAAAAAAAAAFAAgAAAAAAAAAAAAFAAkAAAAAAAAAAAAFAAoAAAAAAAAAAAAFAAsAAAAAAAAAAAAFAAwAAAAAAAAAAAAFAA0AAAAAAAAAAAAFAA4AAAAAAAAAAAAFAA8AAAAAAAAAAAAFABAAAAAAAAAAAAAFABEAAAAAAAAAAAAFABIAAAAAAAAAAAAFABMAAAAAAAAAAAAFABQAAAAAAAAAAAAFABUAAAAAAAAAAAAFABYAAAAAAAAAAAAGABIAAAAAAAAAAAAGABMAAAAAAAAAAAAGABQAAAAAAAAAAAAGABUAAAAAAAAAAAAGABYAAAAAAAAAAAAHABIAAAAAAAAAAAAHABMAAAAAAAAAAAAHABQAAAAAAAAAAAAHABUAAAAAAAAAAAAHABYAAAAAAAAAAAAIABIAAAAAAAAAAAAIABMAAAAAAAAAAAAIABQAAAAAAAAAAAAIABUAAAAAAAAAAAAIABYAAAAAAAAAAAAJABIAAAAAAAAAAAAJABMAAAAAAAAAAAAJABQAAAAAAAAAAAAJABUAAAAAAAAAAAAJABYAAAAAAAAAAAAKABIAAAAAAAAAAAAKABMAAAAAAAAAAAAKABQAAAAAAAAAAAAKABUAAAAAAAAAAAAKABYAAAAAAAAAAAALABIAAAAAAAAAAAALABMAAAAAAAAAAAALABQAAAAAAAAAAAALABUAAAAAAAAAAAALABYAAAAAAAAAAAAMABIAAAAAAAAAAAAMABMAAAAAAAAAAAAMABQAAAAAAAAAAAAMABUAAAAAAAAAAAAMABYAAAAAAAAAAAANABIAAAAAAAAAAAANABMAAAAAAAAAAAANABQAAAAAAAAAAAANABUAAAAAAAAAAAANABYAAAAAAAAAAAAOABIAAAAAAAAAAAAOABMAAAAAAAAAAAAOABQAAAAAAAAAAAAOABUAAAAAAAAAAAAOABYAAAAAAAAAAAAPABIAAAAAAAAAAAAPABMAAAAAAAAAAAAPABQAAAAAAAAAAAAPABUAAAAAAAAAAAAPABYAAAAAAAAAAAAQABIAAAAAAAAAAAAQABMAAAAAAAAAAAAQABQAAAAAAAAAAAAQABUAAAAAAAAAAAAQABYAAAAAAAAAAAARABIAAAAAAAAAAAARABMAAAAAAAAAAAARABQAAAAAAAAAAAARABUAAAAAAAAAAAARABYAAAAAAAAAAAASABIAAAAAAAAAAAASABMAAAAAAAAAAAASABQAAAAAAAAAAAASABUAAAAAAAAAAAASABYAAAAAAAAAAAATABIAAAAAAAAAAAATABMAAAAAAAAAAAATABQAAAAAAAAAAAATABUAAAAAAAAAAAATABYAAAAAAAAAAAAUABIAAAAAAAAAAAAUABMAAAAAAAAAAAAUABQAAAAAAAAAAAAUABUAAAAAAAAAAAAUABYAAAAAAAAAAAAVABIAAAAAAAAAAAAVABMAAAAAAAAAAAAVABQAAAAAAAAAAAAVABUAAAAAAAAAAAAVABYAAAAAAAAAAAARAA8AAAAAAAAAAAARABAAAAAAAAAAAAARABEAAAAAAAAAAAASAA8AAAAAAAAAAAASABAAAAAAAAAAAAASABEAAAAAAAAAAAATAA8AAAAAAAAAAAATABAAAAAAAAAAAAATABEAAAAAAAAAAAAUAA8AAAAAAAAAAAAUABAAAAAAAAAAAAAUABEAAAAAAAAAAAAVAA8AAAAAAAAAAAAVABAAAAAAAAAAAAAVABEAAAAAAAAAAAAGAAAAAAAAAAAAAAAGAAEAAAAAAAAAAAAGAAIAAAAAAAAAAAAGAAMAAAAAAAAAAAAGAAQAAAAAAAAAAAAGAAUAAAAAAAAAAAAGAAYAAAAAAAAAAAAGAAcAAAAAAAAAAAAGAAgAAAAAAAAAAAAHAAAAAAAAAAAAAAAHAAEAAAAAAAAAAAAHAAIAAAAAAAAAAAAHAAMAAAAAAAAAAAAHAAQAAAAAAAAAAAAHAAUAAAAAAAAAAAAHAAYAAAAAAAAAAAAHAAcAAAAAAAAAAAAHAAgAAAAAAAAAAAAIAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAIAAIAAAAAAAAAAAAIAAMAAAAAAAAAAAAIAAQAAAAAAAAAAAAIAAUAAAAAAAAAAAAIAAYAAAAAAAAAAAAIAAcAAAAAAAAAAAAIAAgAAAAAAAAAAAAJAAAAAAAAAAAAAAAJAAEAAAAAAAAAAAAJAAIAAAAAAAAAAAAJAAMAAAAAAAAAAAAJAAQAAAAAAAAAAAAJAAUAAAAAAAAAAAAJAAYAAAAAAAAAAAAJAAcAAAAAAAAAAAAJAAgAAAAAAAAAAAAKAAAAAAAAAAAAAAAKAAEAAAAAAAAAAAAKAAIAAAAAAAAAAAAKAAMAAAAAAAAAAAAKAAQAAAAAAAAAAAAKAAUAAAAAAAAAAAAKAAYAAAAAAAAAAAAKAAcAAAAAAAAAAAAKAAgAAAAAAAAAAAALAAAAAAAAAAAAAAALAAEAAAAAAAAAAAALAAIAAAAAAAAAAAALAAMAAAAAAAAAAAALAAQAAAAAAAAAAAALAAUAAAAAAAAAAAALAAYAAAAAAAAAAAALAAcAAAAAAAAAAAALAAgAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAEAAAAAAAAAAAAMAAIAAAAAAAAAAAAMAAMAAAAAAAAAAAAMAAQAAAAAAAAAAAAMAAUAAAAAAAAAAAAMAAYAAAAAAAAAAAAMAAcAAAAAAAAAAAAMAAgAAAAAAAAAAAANAAAAAAAAAAAAAAANAAEAAAAAAAAAAAANAAIAAAAAAAAAAAANAAMAAAAAAAAAAAANAAQAAAAAAAAAAAANAAUAAAAAAAAAAAANAAYAAAAAAAAAAAANAAcAAAAAAAAAAAANAAgAAAAAAAAAAAAOAAAAAAAAAAAAAAAOAAEAAAAAAAAAAAAOAAIAAAAAAAAAAAAOAAMAAAAAAAAAAAAOAAQAAAAAAAAAAAAOAAUAAAAAAAAAAAAOAAYAAAAAAAAAAAAOAAcAAAAAAAAAAAAOAAgAAAAAAAAAAAAcAAkAAAAAAAAAAAAcAAoAAAAAAAAAAAAcAAsAAAAAAAAAAAAcAAwAAAAAAAAAAAAcAA0AAAAAAAAAAAAcAA4AAAAAAAAAAAAcAA8AAAAAAAAAAAAcABAAAAAAAAAAAAAcABEAAAAAAAAAAAAcABIAAAAAAAAAAAAcABMAAAAAAAAAAAAcABQAAAAAAAAAAAAcABUAAAAAAAAAAAAcABYAAAAAAAAAAAAdAAkAAAAAAAAAAAAdAAoAAAAAAAAAAAAdAAsAAAAAAAAAAAAdAAwAAAAAAAAAAAAdAA0AAAAAAAAAAAAdAA4AAAAAAAAAAAAdAA8AAAAAAAAAAAAdABAAAAAAAAAAAAAdABEAAAAAAAAAAAAdABIAAAAAAAAAAAAdABMAAAAAAAAAAAAdABQAAAAAAAAAAAAdABUAAAAAAAAAAAAdABYAAAAAAAAAAAAeAAkAAAAAAAAAAAAeAAoAAAAAAAAAAAAeAAsAAAAAAAAAAAAeAAwAAAAAAAAAAAAeAA0AAAAAAAAAAAAeAA4AAAAAAAAAAAAeAA8AAAAAAAAAAAAeABAAAAAAAAAAAAAeABEAAAAAAAAAAAAeABIAAAAAAAAAAAAeABMAAAAAAAAAAAAeABQAAAAAAAAAAAAeABUAAAAAAAAAAAAeABYAAAAAAAAAAAAfAAkAAAAAAAAAAAAfAAoAAAAAAAAAAAAfAAsAAAAAAAAAAAAfAAwAAAAAAAAAAAAfAA0AAAAAAAAAAAAfAA4AAAAAAAAAAAAfAA8AAAAAAAAAAAAfABAAAAAAAAAAAAAfABEAAAAAAAAAAAAfABIAAAAAAAAAAAAfABMAAAAAAAAAAAAfABQAAAAAAAAAAAAfABUAAAAAAAAAAAAfABYAAAAAAAAAAAAgAAkAAAAAAAAAAAAgAAoAAAAAAAAAAAAgAAsAAAAAAAAAAAAgAAwAAAAAAAAAAAAgAA0AAAAAAAAAAAAgAA4AAAAAAAAAAAAgAA8AAAAAAAAAAAAgABAAAAAAAAAAAAAgABEAAAAAAAAAAAAgABIAAAAAAAAAAAAgABMAAAAAAAAAAAAgABQAAAAAAAAAAAAgABUAAAAAAAAAAAAgABYAAAAAAAAAAAAhAAkAAAAAAAAAAAAhAAoAAAAAAAAAAAAhAAsAAAAAAAAAAAAhAAwAAAAAAAAAAAAhAA0AAAAAAAAAAAAhAA4AAAAAAAAAAAAhAA8AAAAAAAAAAAAhABAAAAAAAAAAAAAhABEAAAAAAAAAAAAhABIAAAAAAAAAAAAhABMAAAAAAAAAAAAhABQAAAAAAAAAAAAhABUAAAAAAAAAAAAhABYAAAAAAAAAAAAiAAkAAAAAAAAAAAAiAAoAAAAAAAAAAAAiAAsAAAAAAAAAAAAiAAwAAAAAAAAAAAAiAA0AAAAAAAAAAAAiAA4AAAAAAAAAAAAiAA8AAAAAAAAAAAAiABAAAAAAAAAAAAAiABEAAAAAAAAAAAAiABIAAAAAAAAAAAAiABMAAAAAAAAAAAAiABQAAAAAAAAAAAAiABUAAAAAAAAAAAAiABYAAAAAAAAAAAAjAAkAAAAAAAAAAAAjAAoAAAAAAAAAAAAjAAsAAAAAAAAAAAAjAAwAAAAAAAAAAAAjAA0AAAAAAAAAAAAjAA4AAAAAAAAAAAAjAA8AAAAAAAAAAAAjABAAAAAAAAAAAAAjABEAAAAAAAAAAAAjABIAAAAAAAAAAAAjABMAAAAAAAAAAAAjABQAAAAAAAAAAAAjABUAAAAAAAAAAAAjABYAAAAAAAAAAAAkAAkAAAAAAAAAAAAkAAoAAAAAAAAAAAAkAAsAAAAAAAAAAAAkAAwAAAAAAAAAAAAkAA0AAAAAAAAAAAAkAA4AAAAAAAAAAAAkAA8AAAAAAAAAAAAkABAAAAAAAAAAAAAkABEAAAAAAAAAAAAkABIAAAAAAAAAAAAkABMAAAAAAAAAAAAkABQAAAAAAAAAAAAkABUAAAAAAAAAAAAkABYAAAAAAAAAAAAlAAwAAAAAAAAAAAAlAA0AAAAAAAAAAAAlAA4AAAAAAAAAAAAlAA8AAAAAAAAAAAAlABAAAAAAAAAAAAAlABEAAAAAAAAAAAAlABIAAAAAAAAAAAAlABMAAAAAAAAAAAAlABQAAAAAAAAAAAAlABUAAAAAAAAAAAAlABYAAAAAAAAAAAAmAAwAAAAAAAAAAAAmAA0AAAAAAAAAAAAmAA4AAAAAAAAAAAAmAA8AAAAAAAAAAAAmABAAAAAAAAAAAAAmABEAAAAAAAAAAAAmABIAAAAAAAAAAAAmABMAAAAAAAAAAAAmABQAAAAAAAAAAAAmABUAAAAAAAAAAAAmABYAAAAAAAAAAAAnAA0AAAAAAAAAAAAnAA4AAAAAAAAAAAAnAA8AAAAAAAAAAAAnABAAAAAAAAAAAAAnABEAAAAAAAAAAAAnABIAAAAAAAAAAAAnABMAAAAAAAAAAAAnABQAAAAAAAAAAAAnABUAAAAAAAAAAAAnABYAAAAAAAAAAAAoAA0AAAAAAAAAAAAoAA4AAAAAAAAAAAAoAA8AAAAAAAAAAAAoABAAAAAAAAAAAAAoABEAAAAAAAAAAAAoABIAAAAAAAAAAAAoABMAAAAAAAAAAAAoABQAAAAAAAAAAAAoABUAAAAAAAAAAAAoABYAAAAAAAAAAAApAA0AAAAAAAAAAAApAA4AAAAAAAAAAAApAA8AAAAAAAAAAAApABAAAAAAAAAAAAApABEAAAAAAAAAAAApABIAAAAAAAAAAAApABMAAAAAAAAAAAApABQAAAAAAAAAAAApABUAAAAAAAAAAAApABYAAAAAAAAAAAAqAA0AAAAAAAAAAAAqAA4AAAAAAAAAAAAqAA8AAAAAAAAAAAAqABAAAAAAAAAAAAAqABEAAAAAAAAAAAAqABIAAAAAAAAAAAAqABMAAAAAAAAAAAAqABQAAAAAAAAAAAAqABUAAAAAAAAAAAAqABYAAAAAAAAAAAArAAwAAAAAAAAAAAArAA0AAAAAAAAAAAArAA4AAAAAAAAAAAArAA8AAAAAAAAAAAArABAAAAAAAAAAAAArABEAAAAAAAAAAAArABIAAAAAAAAAAAArABMAAAAAAAAAAAArABQAAAAAAAAAAAArABUAAAAAAAAAAAArABYAAAAAAAAAAAAsAAkAAAAAAAAAAAAsAAoAAAAAAAAAAAAsAAsAAAAAAAAAAAAsAAwAAAAAAAAAAAAsAA0AAAAAAAAAAAAsAA4AAAAAAAAAAAAsAA8AAAAAAAAAAAAsABAAAAAAAAAAAAAsABEAAAAAAAAAAAAsABIAAAAAAAAAAAAsABMAAAAAAAAAAAAsABQAAAAAAAAAAAAsABUAAAAAAAAAAAAsABYAAAAAAAAAAAAtAAkAAAAAAAAAAAAtAAoAAAAAAAAAAAAtAAsAAAAAAAAAAAAtAAwAAAAAAAAAAAAtAA0AAAAAAAAAAAAtAA4AAAAAAAAAAAAtAA8AAAAAAAAAAAAtABAAAAAAAAAAAAAtABEAAAAAAAAAAAAtABIAAAAAAAAAAAAtABMAAAAAAAAAAAAtABQAAAAAAAAAAAAtABUAAAAAAAAAAAAtABYAAAAAAAAAAAAuAAkAAAAAAAAAAAAuAAoAAAAAAAAAAAAuAAsAAAAAAAAAAAAuAAwAAAAAAAAAAAAuAA0AAAAAAAAAAAAuAA4AAAAAAAAAAAAuAA8AAAAAAAAAAAAuABAAAAAAAAAAAAAuABEAAAAAAAAAAAAuABIAAAAAAAAAAAAuABMAAAAAAAAAAAAuABQAAAAAAAAAAAAuABUAAAAAAAAAAAAuABYAAAAAAAAAAAAvAAkAAAAAAAAAAAAvAAoAAAAAAAAAAAAvAAsAAAAAAAAAAAAvAAwAAAAAAAAAAAAvAA0AAAAAAAAAAAAvAA4AAAAAAAAAAAAvAA8AAAAAAAAAAAAvABAAAAAAAAAAAAAvABEAAAAAAAAAAAAvABIAAAAAAAAAAAAvABMAAAAAAAAAAAAvABQAAAAAAAAAAAAvABUAAAAAAAAAAAAvABYAAAAAAAAAAAAwAAkAAAAAAAAAAAAwAAoAAAAAAAAAAAAwAAsAAAAAAAAAAAAwAAwAAAAAAAAAAAAwAA0AAAAAAAAAAAAwAA4AAAAAAAAAAAAwAA8AAAAAAAAAAAAwABAAAAAAAAAAAAAwABEAAAAAAAAAAAAwABIAAAAAAAAAAAAwABMAAAAAAAAAAAAwABQAAAAAAAAAAAAwABUAAAAAAAAAAAAwABYAAAAAAAAAAAAxAAkAAAAAAAAAAAAxAAoAAAAAAAAAAAAxAAsAAAAAAAAAAAAxAAwAAAAAAAAAAAAxAA0AAAAAAAAAAAAxAA4AAAAAAAAAAAAxAA8AAAAAAAAAAAAxABAAAAAAAAAAAAAxABEAAAAAAAAAAAAxABIAAAAAAAAAAAAxABMAAAAAAAAAAAAxABQAAAAAAAAAAAAxABUAAAAAAAAAAAAxABYAAAAAAAAAAAAyAAkAAAAAAAAAAAAyAAoAAAAAAAAAAAAyAAsAAAAAAAAAAAAyAAwAAAAAAAAAAAAyAA0AAAAAAAAAAAAyAA4AAAAAAAAAAAAyAA8AAAAAAAAAAAAyABAAAAAAAAAAAAAyABEAAAAAAAAAAAAyABIAAAAAAAAAAAAyABMAAAAAAAAAAAAyABQAAAAAAAAAAAAyABUAAAAAAAAAAAAyABYAAAAAAAAAAAAzAAkAAAAAAAAAAAAzAAoAAAAAAAAAAAAzAAsAAAAAAAAAAAAzAAwAAAAAAAAAAAAzAA0AAAAAAAAAAAAzAA4AAAAAAAAAAAAzAA8AAAAAAAAAAAAzABAAAAAAAAAAAAAzABEAAAAAAAAAAAAzABIAAAAAAAAAAAAzABMAAAAAAAAAAAAzABQAAAAAAAAAAAAzABUAAAAAAAAAAAAzABYAAAAAAAAAAAAlAAsAAAAAAAAAAAArAAsAAAAAAAAAAAAqAAwAAAAAAAAAAAAAAPv/AAAAAAAAAAAAAPz/AAAAAAAAAAAAAP3/AAAAAAAAAAAAAP7/AAAAAAAAAAAAAP//AAAAAAAAAAABAPv/AAAAAAAAAAABAPz/AAAAAAAAAAABAP3/AAAAAAAAAAABAP7/AAAAAAAAAAABAP//AAAAAAAAAAACAPv/AAAAAAAAAAACAPz/AAAAAAAAAAACAP3/AAAAAAAAAAACAP7/AAAAAAAAAAACAP//AAAAAAAAAAADAPv/AAAAAAAAAAADAPz/AAAAAAAAAAADAP3/AAAAAAAAAAADAP7/AAAAAAAAAAADAP//AAAAAAAAAAAEAPv/AAAAAAAAAAAEAPz/AAAAAAAAAAAEAP3/AAAAAAAAAAAEAP7/AAAAAAAAAAAEAP//AAAAAAAAAAAFAPv/AAAAAAAAAAAFAPz/AAAAAAAAAAAFAP3/AAAAAAAAAAAFAP7/AAAAAAAAAAAFAP//AAAAAAAAAAAGAPv/AAAAAAAAAAAGAPz/AAAAAAAAAAAGAP3/AAAAAAAAAAAGAP7/AAAAAAAAAAAGAP//AAAAAAAAAAAHAPv/AAAAAAAAAAAHAPz/AAAAAAAAAAAHAP3/AAAAAAAAAAAHAP7/AAAAAAAAAAAHAP//AAAAAAAAAAAIAPv/AAAAAAAAAAAIAPz/AAAAAAAAAAAIAP3/AAAAAAAAAAAIAP7/AAAAAAAAAAAIAP//AAAAAAAAAAAJAPv/AAAAAAAAAAAJAPz/AAAAAAAAAAAJAP3/AAAAAAAAAAAJAP7/AAAAAAAAAAAJAP//AAAAAAAAAAAKAPv/AAAAAAAAAAAKAPz/AAAAAAAAAAAKAP3/AAAAAAAAAAAKAP7/AAAAAAAAAAAKAP//AAAAAAAAAAALAPv/AAAAAAAAAAALAPz/AAAAAAAAAAALAP3/AAAAAAAAAAALAP7/AAAAAAAAAAALAP//AAAAAAAAAAAMAPv/AAAAAAAAAAAMAPz/AAAAAAAAAAAMAP3/AAAAAAAAAAAMAP7/AAAAAAAAAAAMAP//AAAAAAAAAAANAPv/AAAAAAAAAAANAPz/AAAAAAAAAAANAP3/AAAAAAAAAAANAP7/AAAAAAAAAAANAP//AAAAAAAAAAAOAPv/AAAAAAAAAAAOAPz/AAAAAAAAAAAOAP3/AAAAAAAAAAAOAP7/AAAAAAAAAAAOAP//AAAAAAAAAAAAAPb/AAAAAAAAAAAAAPf/AAAAAAAAAAAAAPj/AAAAAAAAAAAAAPn/AAAAAAAAAAAAAPr/AAAAAAAAAAABAPb/AAAAAAAAAAABAPf/AAAAAAAAAAABAPj/AAAAAAAAAAABAPn/AAAAAAAAAAABAPr/AAAAAAAAAAACAPb/AAAAAAAAAAACAPf/AAAAAAAAAAACAPj/AAAAAAAAAAACAPn/AAAAAAAAAAACAPr/AAAAAAAAAAADAPb/AAAAAAAAAAADAPf/AAAAAAAAAAADAPj/AAAAAAAAAAADAPn/AAAAAAAAAAADAPr/AAAAAAAAAAAEAPb/AAAAAAAAAAAEAPf/AAAAAAAAAAAEAPj/AAAAAAAAAAAEAPn/AAAAAAAAAAAEAPr/AAAAAAAAAAAFAPb/AAAAAAAAAAAFAPf/AAAAAAAAAAAFAPj/AAAAAAAAAAAFAPn/AAAAAAAAAAAFAPr/AAAAAAAAAAAGAPb/AAAAAAAAAAAGAPf/AAAAAAAAAAAGAPj/AAAAAAAAAAAGAPn/AAAAAAAAAAAGAPr/AAAAAAAAAAAHAPb/AAAAAAAAAAAHAPf/AAAAAAAAAAAHAPj/AAAAAAAAAAAHAPn/AAAAAAAAAAAHAPr/AAAAAAAAAAAIAPb/AAAAAAAAAAAIAPf/AAAAAAAAAAAIAPj/AAAAAAAAAAAIAPn/AAAAAAAAAAAIAPr/AAAAAAAAAAAJAPb/AAAAAAAAAAAJAPf/AAAAAAAAAAAJAPj/AAAAAAAAAAAJAPn/AAAAAAAAAAAJAPr/AAAAAAAAAAAKAPb/AAAAAAAAAAAKAPf/AAAAAAAAAAAKAPj/AAAAAAAAAAAKAPn/AAAAAAAAAAAKAPr/AAAAAAAAAAALAPb/AAAAAAAAAAALAPf/AAAAAAAAAAALAPj/AAAAAAAAAAALAPn/AAAAAAAAAAALAPr/AAAAAAAAAAAMAPb/AAAAAAAAAAAMAPf/AAAAAAAAAAAMAPj/AAAAAAAAAAAMAPn/AAAAAAAAAAAMAPr/AAAAAAAAAAANAPb/AAAAAAAAAAANAPf/AAAAAAAAAAANAPj/AAAAAAAAAAANAPn/AAAAAAAAAAANAPr/AAAAAAAAAAAOAPb/AAAAAAAAAAAOAPf/AAAAAAAAAAAOAPj/AAAAAAAAAAAOAPn/AAAAAAAAAAAOAPr/AAAAAAAAAAAPAPb/AAAAAAAAAAAPAPf/AAAAAAAAAAAPAPj/AAAAAAAAAAAPAPn/AAAAAAAAAAAPAPr/AAAAAAAAAAAQAPb/AAAAAAAAAAAQAPf/AAAAAAAAAAAQAPj/AAAAAAAAAAAQAPn/AAAAAAAAAAAQAPr/AAAAAAAAAAARAPb/AAAAAAAAAAARAPf/AAAAAAAAAAARAPj/AAAAAAAAAAARAPn/AAAAAAAAAAARAPr/AAAAAAAAAAASAPb/AAAAAAAAAAASAPf/AAAAAAAAAAASAPj/AAAAAAAAAAASAPn/AAAAAAAAAAASAPr/AAAAAAAAAAATAPb/AAAAAAAAAAATAPf/AAAAAAAAAAATAPj/AAAAAAAAAAATAPn/AAAAAAAAAAATAPr/AAAAAAAAAAAUAPb/AAAAAAAAAAAUAPf/AAAAAAAAAAAUAPj/AAAAAAAAAAAUAPn/AAAAAAAAAAAUAPr/AAAAAAAAAAAVAPb/AAAAAAAAAAAVAPf/AAAAAAAAAAAVAPj/AAAAAAAAAAAVAPn/AAAAAAAAAAAVAPr/AAAAAAAAAAAWAPb/AAAAAAAAAAAWAPf/AAAAAAAAAAAWAPj/AAAAAAAAAAAWAPn/AAAAAAAAAAAWAPr/AAAAAAAAAAAXAPb/AAAAAAAAAAAXAPf/AAAAAAAAAAAXAPj/AAAAAAAAAAAXAPn/AAAAAAAAAAAXAPr/AAAAAAAAAAAYAPb/AAAAAAAAAAAYAPf/AAAAAAAAAAAYAPj/AAAAAAAAAAAYAPn/AAAAAAAAAAAYAPr/AAAAAAAAAAAZAPb/AAAAAAAAAAAZAPf/AAAAAAAAAAAZAPj/AAAAAAAAAAAZAPn/AAAAAAAAAAAZAPr/AAAAAAAAAAAaAPb/AAAAAAAAAAAaAPf/AAAAAAAAAAAaAPj/AAAAAAAAAAAaAPn/AAAAAAAAAAAaAPr/AAAAAAAAAAAbAPb/AAAAAAAAAAAbAPf/AAAAAAAAAAAbAPj/AAAAAAAAAAAbAPn/AAAAAAAAAAAbAPr/AAAAAAAAAAAcAPb/AAAAAAAAAAAcAPf/AAAAAAAAAAAcAPj/AAAAAAAAAAAcAPn/AAAAAAAAAAAcAPr/AAAAAAAAAAAdAPb/AAAAAAAAAAAdAPf/AAAAAAAAAAAdAPj/AAAAAAAAAAAdAPn/AAAAAAAAAAAdAPr/AAAAAAAAAAAeAPb/AAAAAAAAAAAeAPf/AAAAAAAAAAAeAPj/AAAAAAAAAAAeAPn/AAAAAAAAAAAeAPr/AAAAAAAAAAAfAPb/AAAAAAAAAAAfAPf/AAAAAAAAAAAfAPj/AAAAAAAAAAAfAPn/AAAAAAAAAAAfAPr/AAAAAAAAAAAgAPb/AAAAAAAAAAAgAPf/AAAAAAAAAAAgAPj/AAAAAAAAAAAgAPn/AAAAAAAAAAAgAPr/AAAAAAAAAAAhAPb/AAAAAAAAAAAhAPf/AAAAAAAAAAAhAPj/AAAAAAAAAAAhAPn/AAAAAAAAAAAhAPr/AAAAAAAAAAAiAPb/AAAAAAAAAAAiAPf/AAAAAAAAAAAiAPj/AAAAAAAAAAAiAPn/AAAAAAAAAAAiAPr/AAAAAAAAAAAjAPb/AAAAAAAAAAAjAPf/AAAAAAAAAAAjAPj/AAAAAAAAAAAjAPn/AAAAAAAAAAAjAPr/AAAAAAAAAAAkAPb/AAAAAAAAAAAkAPf/AAAAAAAAAAAkAPj/AAAAAAAAAAAkAPn/AAAAAAAAAAAkAPr/AAAAAAAAAAAlAPb/AAAAAAAAAAAlAPf/AAAAAAAAAAAlAPj/AAAAAAAAAAAlAPn/AAAAAAAAAAAlAPr/AAAAAAAAAAAmAPb/AAAAAAAAAAAmAPf/AAAAAAAAAAAmAPj/AAAAAAAAAAAmAPn/AAAAAAAAAAAmAPr/AAAAAAAAAAAnAPb/AAAAAAAAAAAnAPf/AAAAAAAAAAAnAPj/AAAAAAAAAAAnAPn/AAAAAAAAAAAnAPr/AAAAAAAAAAAoAPb/AAAAAAAAAAAoAPf/AAAAAAAAAAAoAPj/AAAAAAAAAAAoAPn/AAAAAAAAAAAoAPr/AAAAAAAAAAApAPb/AAAAAAAAAAApAPf/AAAAAAAAAAApAPj/AAAAAAAAAAApAPn/AAAAAAAAAAApAPr/AAAAAAAAAAAqAPb/AAAAAAAAAAAqAPf/AAAAAAAAAAAqAPj/AAAAAAAAAAAqAPn/AAAAAAAAAAAqAPr/AAAAAAAAAAArAPb/AAAAAAAAAAArAPf/AAAAAAAAAAArAPj/AAAAAAAAAAArAPn/AAAAAAAAAAArAPr/AAAAAAAAAAAsAPb/AAAAAAAAAAAsAPf/AAAAAAAAAAAsAPj/AAAAAAAAAAAsAPn/AAAAAAAAAAAsAPr/AAAAAAAAAAAtAPb/AAAAAAAAAAAtAPf/AAAAAAAAAAAtAPj/AAAAAAAAAAAtAPn/AAAAAAAAAAAtAPr/AAAAAAAAAAAuAPb/AAAAAAAAAAAuAPf/AAAAAAAAAAAuAPj/AAAAAAAAAAAuAPn/AAAAAAAAAAAuAPr/AAAAAAAAAAAvAPb/AAAAAAAAAAAvAPf/AAAAAAAAAAAvAPj/AAAAAAAAAAAvAPn/AAAAAAAAAAAvAPr/AAAAAAAAAAAwAPb/AAAAAAAAAAAwAPf/AAAAAAAAAAAwAPj/AAAAAAAAAAAwAPn/AAAAAAAAAAAwAPr/AAAAAAAAAAAxAPb/AAAAAAAAAAAxAPf/AAAAAAAAAAAxAPj/AAAAAAAAAAAxAPn/AAAAAAAAAAAxAPr/AAAAAAAAAAAyAPb/AAAAAAAAAAAyAPf/AAAAAAAAAAAyAPj/AAAAAAAAAAAyAPn/AAAAAAAAAAAyAPr/AAAAAAAAAAAzAPb/AAAAAAAAAAAzAPf/AAAAAAAAAAAzAPj/AAAAAAAAAAAzAPn/AAAAAAAAAAAzAPr/AAAAAAAAAAA0APb/AAAAAAAAAAA0APf/AAAAAAAAAAA0APj/AAAAAAAAAAA0APn/AAAAAAAAAAA0APr/AAAAAAAAAAA1APb/AAAAAAAAAAA1APf/AAAAAAAAAAA1APj/AAAAAAAAAAA1APn/AAAAAAAAAAA1APr/AAAAAAAAAAA2APb/AAAAAAAAAAA2APf/AAAAAAAAAAA2APj/AAAAAAAAAAA2APn/AAAAAAAAAAA2APr/AAAAAAAAAAA3APb/AAAAAAAAAAA3APf/AAAAAAAAAAA3APj/AAAAAAAAAAA3APn/AAAAAAAAAAA3APr/AAAAAAAAAAA4APb/AAAAAAAAAAA4APf/AAAAAAAAAAA4APj/AAAAAAAAAAA4APn/AAAAAAAAAAA4APr/AAAAAAAAAAA5APb/AAAAAAAAAAA5APf/AAAAAAAAAAA5APj/AAAAAAAAAAA5APn/AAAAAAAAAAA5APr/AAAAAAAAAAA6APb/AAAAAAAAAAA6APf/AAAAAAAAAAA6APj/AAAAAAAAAAA6APn/AAAAAAAAAAA6APr/AAAAAAAAAAAWAA8AAAABAAAAAAAWABAAAAABAAAAAAAWABEAAAABAAAAAAAWABIAAAABAAAAAAAWABMAAAABAAAAAAAWABQAAAABAAAAAAAWABUAAAABAAAAAAAWABYAAAABAAAAAAAbAA8AAAABAAAAAAAbABAAAAABAAAAAAAbABEAAAABAAAAAAAbABIAAAABAAAAAAAbABMAAAABAAAAAAAbABQAAAABAAAAAAAbABUAAAABAAAAAAAbABYAAAABAAAAAAAhAAgAAAABAAAAAAAiAAgAAAABAAAAAAAjAAgAAAABAAAAAABKAAkAAAAAAAAAAABKAAoAAAAAAAAAAABKAAsAAAAAAAAAAABKAAwAAAAAAAAAAABLAAkAAAAAAAAAAABLAAoAAAAAAAAAAABLAAsAAAAAAAAAAABLAAwAAAAAAAAAAABKAAUAAAAAAAAAAABKAAYAAAAAAAAAAABKAAcAAAAAAAAAAABKAAgAAAAAAAAAAABKAA0AAAAAAAAAAABLAAUAAAAAAAAAAABLAAYAAAAAAAAAAABLAAcAAAAAAAAAAABLAAgAAAAAAAAAAABLAA0AAAAAAAAAAABQABMAAAAAAAAAAABQABQAAAAAAAAAAABQABUAAAAAAAAAAABQABYAAAAAAAAAAABQABcAAAAAAAAAAABRABMAAAAAAAAAAABRABQAAAAAAAAAAABRABUAAAAAAAAAAABRABYAAAAAAAAAAABRABcAAAAAAAAAAABSABMAAAAAAAAAAABSABQAAAAAAAAAAABSABUAAAAAAAAAAABSABYAAAAAAAAAAABSABcAAAAAAAAAAABTABMAAAAAAAAAAABTABQAAAAAAAAAAABTABUAAAAAAAAAAABTABYAAAAAAAAAAABTABcAAAAAAAAAAABUABMAAAAAAAAAAABUABQAAAAAAAAAAABUABUAAAAAAAAAAABUABYAAAAAAAAAAABUABcAAAAAAAAAAABVABMAAAAAAAAAAABVABQAAAAAAAAAAABVABUAAAAAAAAAAABVABYAAAAAAAAAAABVABcAAAAAAAAAAABWABMAAAAAAAAAAABWABQAAAAAAAAAAABWABUAAAAAAAAAAABWABYAAAAAAAAAAABWABcAAAAAAAAAAABXAAsAAAAAAAAAAABXAAwAAAAAAAAAAABXAA0AAAAAAAAAAABXAA4AAAAAAAAAAABXABMAAAAAAAAAAABXABQAAAAAAAAAAABXABUAAAAAAAAAAABXABYAAAAAAAAAAABXABcAAAAAAAAAAABYAAsAAAAAAAAAAABYAAwAAAAAAAAAAABYAA0AAAAAAAAAAABYAA4AAAAAAAAAAABYABMAAAAAAAAAAABYABQAAAAAAAAAAABYABUAAAAAAAAAAABYABYAAAAAAAAAAABYABcAAAAAAAAAAABZAAsAAAAAAAAAAABZAAwAAAAAAAAAAABZAA0AAAAAAAAAAABZAA4AAAAAAAAAAABZABMAAAAAAAAAAABZABQAAAAAAAAAAABZABUAAAAAAAAAAABZABYAAAAAAAAAAABZABcAAAAAAAAAAABaAAsAAAAAAAAAAABaAAwAAAAAAAAAAABaAA0AAAAAAAAAAABaAA4AAAAAAAAAAABaABMAAAAAAAAAAABaABQAAAAAAAAAAABaABUAAAAAAAAAAABaABYAAAAAAAAAAABaABcAAAAAAAAAAABbAAsAAAAAAAAAAABbAAwAAAAAAAAAAABbAA0AAAAAAAAAAABbAA4AAAAAAAAAAABbABMAAAAAAAAAAABbABQAAAAAAAAAAABbABUAAAAAAAAAAABbABYAAAAAAAAAAABbABcAAAAAAAAAAABcAAsAAAAAAAAAAABcAAwAAAAAAAAAAABcAA0AAAAAAAAAAABcAA4AAAAAAAAAAABcABMAAAAAAAAAAABcABQAAAAAAAAAAABcABUAAAAAAAAAAABcABYAAAAAAAAAAABcABcAAAAAAAAAAABdAAsAAAAAAAAAAABdAAwAAAAAAAAAAABdAA0AAAAAAAAAAABdAA4AAAAAAAAAAABdABMAAAAAAAAAAABdABQAAAAAAAAAAABdABUAAAAAAAAAAABdABYAAAAAAAAAAABdABcAAAAAAAAAAABeAAsAAAAAAAAAAABeAAwAAAAAAAAAAABeAA0AAAAAAAAAAABeAA4AAAAAAAAAAABeABMAAAAAAAAAAABeABQAAAAAAAAAAABeABUAAAAAAAAAAABeABYAAAAAAAAAAABeABcAAAAAAAAAAAA0AA8AAAAAAAAAAAA0ABAAAAAAAAAAAAA0ABEAAAAAAAAAAAA0ABIAAAAAAAAAAAA0ABMAAAAAAAAAAAA0ABQAAAAAAAAAAAA0ABUAAAAAAAAAAAA0ABYAAAAAAAAAAAA1AA8AAAAAAAAAAAA1ABAAAAAAAAAAAAA1ABEAAAAAAAAAAAA1ABIAAAAAAAAAAAA1ABMAAAAAAAAAAAA1ABQAAAAAAAAAAAA1ABUAAAAAAAAAAAA1ABYAAAAAAAAAAAA2AA8AAAAAAAAAAAA2ABAAAAAAAAAAAAA2ABEAAAAAAAAAAAA2ABIAAAAAAAAAAAA2ABMAAAAAAAAAAAA2ABQAAAAAAAAAAAA2ABUAAAAAAAAAAAA2ABYAAAAAAAAAAAA3AA8AAAAAAAAAAAA3ABAAAAAAAAAAAAA3ABEAAAAAAAAAAAA3ABIAAAAAAAAAAAA3ABMAAAAAAAAAAAA3ABQAAAAAAAAAAAA3ABUAAAAAAAAAAAA3ABYAAAAAAAAAAAA4AA8AAAAAAAAAAAA4ABAAAAAAAAAAAAA4ABEAAAAAAAAAAAA4ABIAAAAAAAAAAAA4ABMAAAAAAAAAAAA4ABQAAAAAAAAAAAA4ABUAAAAAAAAAAAA4ABYAAAAAAAAAAAA5AA8AAAAAAAAAAAA5ABAAAAAAAAAAAAA5ABEAAAAAAAAAAAA5ABIAAAAAAAAAAAA5ABMAAAAAAAAAAAA5ABQAAAAAAAAAAAA5ABUAAAAAAAAAAAA5ABYAAAAAAAAAAAA6AA8AAAAAAAAAAAA6ABAAAAAAAAAAAAA6ABEAAAAAAAAAAAA6ABIAAAAAAAAAAAA6ABMAAAAAAAAAAAA6ABQAAAAAAAAAAAA6ABUAAAAAAAAAAAA6ABYAAAAAAAAAAAA7AA8AAAAAAAAAAAA7ABAAAAAAAAAAAAA7ABEAAAAAAAAAAAA7ABIAAAAAAAAAAAA7ABMAAAAAAAAAAAA7ABQAAAAAAAAAAAA7ABUAAAAAAAAAAAA7ABYAAAAAAAAAAAA8AA8AAAAAAAAAAAA8ABAAAAAAAAAAAAA8ABEAAAAAAAAAAAA8ABIAAAAAAAAAAAA8ABMAAAAAAAAAAAA8ABQAAAAAAAAAAAA8ABUAAAAAAAAAAAA8ABYAAAAAAAAAAAA9AA8AAAAAAAAAAAA9ABAAAAAAAAAAAAA9ABEAAAAAAAAAAAA9ABIAAAAAAAAAAAA9ABMAAAAAAAAAAAA9ABQAAAAAAAAAAAA9ABUAAAAAAAAAAAA9ABYAAAAAAAAAAAA+AA8AAAAAAAAAAAA+ABAAAAAAAAAAAAA+ABEAAAAAAAAAAAA+ABIAAAAAAAAAAAA+ABMAAAAAAAAAAAA+ABQAAAAAAAAAAAA+ABUAAAAAAAAAAAA+ABYAAAAAAAAAAAA/AA8AAAAAAAAAAAA/ABAAAAAAAAAAAAA/ABEAAAAAAAAAAAA/ABIAAAAAAAAAAAA/ABMAAAAAAAAAAAA/ABQAAAAAAAAAAAA/ABUAAAAAAAAAAAA/ABYAAAAAAAAAAABAAA8AAAAAAAAAAABAABAAAAAAAAAAAABAABEAAAAAAAAAAABAABIAAAAAAAAAAABAABMAAAAAAAAAAABAABQAAAAAAAAAAABAABUAAAAAAAAAAABAABYAAAAAAAAAAABBAA8AAAAAAAAAAABBABAAAAAAAAAAAABBABEAAAAAAAAAAABBABIAAAAAAAAAAABBABMAAAAAAAAAAABBABQAAAAAAAAAAABBABUAAAAAAAAAAABBABYAAAAAAAAAAAA0AAkAAAABAAAAAAA0AAoAAAABAAAAAAA0AAsAAAABAAAAAAA0AAwAAAABAAAAAAA0AA0AAAABAAAAAAA0AA4AAAABAAAAAAA1AA4AAAABAAAAAAA2AA4AAAABAAAAAAA3AA4AAAABAAAAAAA4AA4AAAABAAAAAABJAAUAAAABAAAAAABJAAYAAAABAAAAAABJAAcAAAABAAAAAABJAAgAAAABAAAAAABJAAkAAAABAAAAAABJAAoAAAABAAAAAABJAAsAAAABAAAAAABJAAwAAAABAAAAAABJAA0AAAABAAAAAABMAAkAAAABAAAAAAA=") + +[node name="PlayerController" parent="." node_paths=PackedStringArray("auto_controlled_avatar") instance=ExtResource("2_gslp7")] +auto_controlled_avatar = NodePath("../Avatar") + +[node name="Avatar" parent="." instance=ExtResource("3_6jw57")] +position = Vector2(218, 251) +collision_mask = 4 + +[node name="EventTriggerDoor" parent="." instance=ExtResource("4_p0ota")] +position = Vector2(342, 176) + +[node name="PropComponent" type="Node" parent="EventTriggerDoor"] +script = ExtResource("5_gslp7") +metadata/_custom_type_script = "uid://b4menkyub4ce7" + +[node name="States" type="Node" parent="EventTriggerDoor/PropComponent"] + +[node name="Close" type="Node" parent="EventTriggerDoor/PropComponent/States"] +script = ExtResource("6_6jw57") +state_id = 0 +effects = Array[ExtResource("7_2t6pm")]([SubResource("Resource_2t6pm")]) +metadata/_custom_type_script = "uid://7lml6d1t5xtq" + +[node name="Open" type="Node" parent="EventTriggerDoor/PropComponent/States"] +script = ExtResource("6_6jw57") +state_id = 1 +effects = Array[ExtResource("7_2t6pm")]([SubResource("Resource_g37lb")]) +metadata/_custom_type_script = "uid://7lml6d1t5xtq" + +[node name="FromClose" type="Node" parent="EventTriggerDoor/PropComponent/States/Open"] +script = ExtResource("8_xkd7q") +from_state_id = 0 +effects = Array[ExtResource("7_2t6pm")]([SubResource("Resource_xkd7q")]) +metadata/_custom_type_script = "uid://jeybblac0kg2" diff --git a/_props/_prefabs/door.gd b/_props/_prefabs/door.gd new file mode 100644 index 0000000..112767d --- /dev/null +++ b/_props/_prefabs/door.gd @@ -0,0 +1,7 @@ +extends AnimatableBody2D + +func door_open() -> void: + pass + +func door_close() -> void: + pass diff --git a/_props/_prefabs/door.gd.uid b/_props/_prefabs/door.gd.uid new file mode 100644 index 0000000..0ae168a --- /dev/null +++ b/_props/_prefabs/door.gd.uid @@ -0,0 +1 @@ +uid://byntg0bbp8nar diff --git a/_props/_prefabs/door.tscn b/_props/_prefabs/door.tscn new file mode 100644 index 0000000..85beeb6 --- /dev/null +++ b/_props/_prefabs/door.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=4 format=3 uid="uid://5ia817pm76x1"] + +[ext_resource type="Script" uid="uid://byntg0bbp8nar" path="res://_props/_prefabs/door.gd" id="1_gt1uq"] +[ext_resource type="Texture2D" uid="uid://c673bap4b12fx" path="res://icon.svg" id="2_f05xd"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_g1m3x"] +size = Vector2(20, 128) + +[node name="Door" type="AnimatableBody2D"] +script = ExtResource("1_gt1uq") + +[node name="Sprite2D" type="Sprite2D" parent="."] +scale = Vector2(0.16, 1) +texture = ExtResource("2_f05xd") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("RectangleShape2D_g1m3x") diff --git a/_props/tools/player_trigger_volumn.gd b/_props/_prefabs/player_trigger_volumn.gd similarity index 100% rename from _props/tools/player_trigger_volumn.gd rename to _props/_prefabs/player_trigger_volumn.gd diff --git a/_props/tools/player_trigger_volumn.gd.uid b/_props/_prefabs/player_trigger_volumn.gd.uid similarity index 100% rename from _props/tools/player_trigger_volumn.gd.uid rename to _props/_prefabs/player_trigger_volumn.gd.uid diff --git a/_props/tools/player_trigger_volumn.tscn b/_props/_prefabs/player_trigger_volumn.tscn similarity index 86% rename from _props/tools/player_trigger_volumn.tscn rename to _props/_prefabs/player_trigger_volumn.tscn index 42ab855..e784418 100644 --- a/_props/tools/player_trigger_volumn.tscn +++ b/_props/_prefabs/player_trigger_volumn.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://bonrls3iuhdqb"] -[ext_resource type="Script" uid="uid://c25ea2nypjah7" path="res://_props/tools/player_trigger_volumn.gd" id="1_qrafk"] +[ext_resource type="Script" uid="uid://c25ea2nypjah7" path="res://_props/_prefabs/player_trigger_volumn.gd" id="1_qrafk"] [node name="PlayerTriggerVolumn" type="Area2D"] editor_description = "此类在检测到玩家时会发出signal,可以与其他的需要检测玩家的scene组合使用。 diff --git a/_props/tools/rock.gd b/_props/_prefabs/rock.gd similarity index 100% rename from _props/tools/rock.gd rename to _props/_prefabs/rock.gd diff --git a/_props/tools/rock.gd.uid b/_props/_prefabs/rock.gd.uid similarity index 100% rename from _props/tools/rock.gd.uid rename to _props/_prefabs/rock.gd.uid diff --git a/_props/tools/rock.tscn b/_props/_prefabs/rock.tscn similarity index 87% rename from _props/tools/rock.tscn rename to _props/_prefabs/rock.tscn index c52d99e..df8f299 100644 --- a/_props/tools/rock.tscn +++ b/_props/_prefabs/rock.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://cmjwk4gr1nfns"] -[ext_resource type="Script" uid="uid://hme2aiy2gff7" path="res://_props/tools/rock.gd" id="1_60pcp"] +[ext_resource type="Script" uid="uid://hme2aiy2gff7" path="res://_props/_prefabs/rock.gd" id="1_60pcp"] [node name="rock" type="CharacterBody2D"] collision_layer = 4 diff --git a/_props/tools/rock.tscn3416382947.tmp b/_props/_prefabs/rock.tscn3416382947.tmp similarity index 100% rename from _props/tools/rock.tscn3416382947.tmp rename to _props/_prefabs/rock.tscn3416382947.tmp diff --git a/_props/tools/rock.tscn3421406171.tmp b/_props/_prefabs/rock.tscn3421406171.tmp similarity index 100% rename from _props/tools/rock.tscn3421406171.tmp rename to _props/_prefabs/rock.tscn3421406171.tmp diff --git a/_props/tools/rock.tscn3425658289.tmp b/_props/_prefabs/rock.tscn3425658289.tmp similarity index 100% rename from _props/tools/rock.tscn3425658289.tmp rename to _props/_prefabs/rock.tscn3425658289.tmp diff --git a/_props/tools/rock.tscn3428328998.tmp b/_props/_prefabs/rock.tscn3428328998.tmp similarity index 100% rename from _props/tools/rock.tscn3428328998.tmp rename to _props/_prefabs/rock.tscn3428328998.tmp diff --git a/_props/tools/rock.tscn3431253549.tmp b/_props/_prefabs/rock.tscn3431253549.tmp similarity index 100% rename from _props/tools/rock.tscn3431253549.tmp rename to _props/_prefabs/rock.tscn3431253549.tmp diff --git a/_props/tools/rock.tscn3469291705.tmp b/_props/_prefabs/rock.tscn3469291705.tmp similarity index 100% rename from _props/tools/rock.tscn3469291705.tmp rename to _props/_prefabs/rock.tscn3469291705.tmp diff --git a/_props/door_manager/event_trigger_door.gd b/_props/door_manager/event_trigger_door.gd new file mode 100644 index 0000000..651a610 --- /dev/null +++ b/_props/door_manager/event_trigger_door.gd @@ -0,0 +1,80 @@ +extends Node2D + +##标记位 +@onready var door_open_poser: Marker2D = %DoorOpenPoser +@onready var door_close_poser: Marker2D = %DoorClosePoser +@onready var door: AnimatableBody2D = %Door + +var _move_tween: Tween # 用来管理当前 tween + +##门的状态,默认为0(关闭),可以切换为1(开启) +var door_state_id: int = 0 +##门移动动画结束广播,输出0为关闭,输出1为开启 +signal door_move_finished(int) + +func _ready() -> void: + await get_tree().create_timer(.2).timeout + $PropComponent.change_state(1,true) + +##开门 +func door_open() -> void: + door_move(door_open_poser) + +##关门 +func door_close() -> void: + door_move(door_close_poser) + +##门的移动 +func door_move(poser: Node2D, duration := 0.4) -> void: + if not poser or not door: + return + + # 如果上一次 tween 还在,先杀掉(非常重要) + if _move_tween and _move_tween.is_running(): + _move_tween.kill() + + var target_pos: Vector2 = poser.global_position + + _move_tween = create_tween() + _move_tween.set_trans(Tween.TRANS_SINE) + _move_tween.set_ease(Tween.EASE_IN_OUT) + + _move_tween.tween_property( + door, + "global_position", + target_pos, + duration + ) + + ##移动结束的返回信号 + _move_tween.finished.connect( + Callable(self, "_on_door_move_finished").bind(poser) + ) + +##直接重置door的位置到某个poser +func reset_door(poser: Node2D)-> void: + if not is_node_ready(): + await ready + + if not poser: return + door.global_position = poser.global_position + +##直接重置door的位置到某个poser的id,id可以见上面 +func reset_door_state_id(id:int = 0)-> void: + if not is_node_ready(): + await ready + + if id != 0 and id != 1: return + if door_state_id == id: return + + var n = door_open_poser if id == 1 else door_close_poser + door_state_id = id + reset_door(n) + +##门开关结束的广播 +func _on_door_move_finished(poser: Node2D) -> void: + if poser == door_open_poser: + door_move_finished.emit(1) + + if poser == door_close_poser: + door_move_finished.emit(0) diff --git a/_props/door_manager/event_trigger_door.gd.uid b/_props/door_manager/event_trigger_door.gd.uid new file mode 100644 index 0000000..1d9c069 --- /dev/null +++ b/_props/door_manager/event_trigger_door.gd.uid @@ -0,0 +1 @@ +uid://cup8c7j4e6xpf diff --git a/_props/door_manager/event_trigger_door.tscn b/_props/door_manager/event_trigger_door.tscn new file mode 100644 index 0000000..a1c3262 --- /dev/null +++ b/_props/door_manager/event_trigger_door.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=3 format=3 uid="uid://b5nx4dntm0gyn"] + +[ext_resource type="PackedScene" uid="uid://5ia817pm76x1" path="res://_props/_prefabs/door.tscn" id="1_3ghu3"] +[ext_resource type="Script" uid="uid://cup8c7j4e6xpf" path="res://_props/door_manager/event_trigger_door.gd" id="1_iprsb"] + +[node name="EventTriggerDoor" type="Node2D"] +script = ExtResource("1_iprsb") + +[node name="Door" parent="." instance=ExtResource("1_3ghu3")] +unique_name_in_owner = true + +[node name="DoorClosePoser" type="Marker2D" parent="."] +unique_name_in_owner = true + +[node name="DoorOpenPoser" type="Marker2D" parent="."] +unique_name_in_owner = true +position = Vector2(0, -90) diff --git a/_props/door_manager/prop_states/close.gd b/_props/door_manager/prop_states/close.gd new file mode 100644 index 0000000..e69de29 diff --git a/_props/door_manager/prop_states/close.gd.uid b/_props/door_manager/prop_states/close.gd.uid new file mode 100644 index 0000000..a36f2a7 --- /dev/null +++ b/_props/door_manager/prop_states/close.gd.uid @@ -0,0 +1 @@ +uid://dm28i1f2r18b8 diff --git a/_props/door_manager/prop_states/t_door_open_f_close.gd b/_props/door_manager/prop_states/t_door_open_f_close.gd new file mode 100644 index 0000000..cd5649e --- /dev/null +++ b/_props/door_manager/prop_states/t_door_open_f_close.gd @@ -0,0 +1,7 @@ +extends ReedTransition + +func execute(from: ReedPropState, to: ReedPropState, ctx: Dictionary) -> bool: + super.execute(from,to,ctx) + to._owner.call + + diff --git a/_props/door_manager/prop_states/t_door_open_f_close.gd.uid b/_props/door_manager/prop_states/t_door_open_f_close.gd.uid new file mode 100644 index 0000000..565ac68 --- /dev/null +++ b/_props/door_manager/prop_states/t_door_open_f_close.gd.uid @@ -0,0 +1 @@ +uid://csbvukpwc7g6p diff --git a/_props/trigger_fall_rock/trigger_fall_rock.tscn b/_props/trigger_fall_rock/trigger_fall_rock.tscn index 828ab97..d6f3a90 100644 --- a/_props/trigger_fall_rock/trigger_fall_rock.tscn +++ b/_props/trigger_fall_rock/trigger_fall_rock.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=7 format=3 uid="uid://knrcnoedxvm6"] -[ext_resource type="PackedScene" uid="uid://bonrls3iuhdqb" path="res://_props/tools/player_trigger_volumn.tscn" id="1_mvp6g"] -[ext_resource type="PackedScene" uid="uid://cmjwk4gr1nfns" path="res://_props/tools/rock.tscn" id="1_nh18e"] +[ext_resource type="PackedScene" uid="uid://bonrls3iuhdqb" path="res://_props/_prefabs/player_trigger_volumn.tscn" id="1_mvp6g"] +[ext_resource type="PackedScene" uid="uid://cmjwk4gr1nfns" path="res://_props/_prefabs/rock.tscn" id="1_nh18e"] [ext_resource type="Script" uid="uid://b8yl6l3tlam86" path="res://_props/trigger_fall_rock/trigger_fall_rock.gd" id="1_vv0hj"] [ext_resource type="Texture2D" uid="uid://c673bap4b12fx" path="res://icon.svg" id="2_xilvp"] diff --git a/addons/reedscene/act/act_manager.gd b/addons/reedscene/act/act_manager.gd new file mode 100644 index 0000000..e2da7e1 --- /dev/null +++ b/addons/reedscene/act/act_manager.gd @@ -0,0 +1 @@ +class_name ActManager extends Node diff --git a/addons/reedscene/act/act_manager.gd.uid b/addons/reedscene/act/act_manager.gd.uid new file mode 100644 index 0000000..f967431 --- /dev/null +++ b/addons/reedscene/act/act_manager.gd.uid @@ -0,0 +1 @@ +uid://dsgl7lbyjsiif diff --git a/addons/reedscene/prop/PropComponent.gd b/addons/reedscene/prop/PropComponent.gd new file mode 100644 index 0000000..d818177 --- /dev/null +++ b/addons/reedscene/prop/PropComponent.gd @@ -0,0 +1,178 @@ +'''此类为Prop的管理组件类,任何的Prop,其至少需要在此类的最上层的子层添加该组件 + 该管理器,在添加入Tree时,会自动的添加一个States节点作为其所有state的root, + 并且添加一个默认的state作为其子节点。 +''' + +@tool +@icon("res://addons/reedscene/prop/icon/prop_icon.svg") +class_name PropComponent extends Node + +## ============================== +## Export +## ============================== + +##此物件的描述ID +@export var prop_id: int + +##初始的默认state_id +@export var initial_state_id: int = 0 + +##是否需要输出错误 +@export var debug_log := false + +##是否等待 +@export var should_wait_owner_ready :bool = true + +##状态切换的信号 +signal state_changed(from_state: int, to_state: int, ctx: Dictionary) + +##state的根节点,所有的state都需要连在根节点上 +var _states_root: Node +var _state_map: Dictionary = {} +var _current: ReedPropState = null + +const states_root_name := "States" +const DEFAULT_STATE_ID := 0 + + +func _enter_tree() -> void: + if Engine.is_editor_hint(): + _editor_ensure_states_root() + +func _ready() -> void: + _build_state_cache() + + if not Engine.is_editor_hint(): + if should_wait_owner_ready: await owner.ready + + _init_states() + if _current == null and initial_state_id >= 0: + change_state(initial_state_id, false, { + "reason": "INIT", + "instant": true + }) + +##映射State到stateID +func _build_state_cache() -> void: + _state_map.clear() + + _states_root = get_node_or_null(states_root_name) + if _states_root == null: + push_warning("[PropComponent:%s] States root not found" % prop_id) + return + + for c in _states_root.get_children(): + if c is ReedPropState: + var s := c as ReedPropState + if _state_map.has(s.state_id): + push_error("[PropComponent:%s] Duplicate state_id: %d" % [prop_id, s.state_id]) + continue + _state_map[s.state_id] = s + + if debug_log: + print("[PropComponent:%s] States:", _state_map.keys()) + +##检查当前是否存在当前Id的State +func has_state(state_id: int) -> bool: + return _state_map.has(state_id) + +##获取当前的状态ID +func get_current_state_id() -> int: + return _current.state_id if _current else -1 + +##初始化状态 +func _init_states() -> void: + var owner := get_parent() + if owner == null: + push_error("[PropComponent:%s] Owner node not found." % prop_id) + return + + for s in _state_map.values(): + var ok :bool = s.init(owner, self) + if not ok: + push_error("[PropComponent:%s] State init failed: %s" + % [prop_id, s.name]) + +## 切换状态,如果 use_trans 为 true,则会优先检查 next state 下是否存在可用的 Transition +func change_state(state_id: int, use_trans: bool, ctx: Dictionary = {}) -> bool: + if not _state_map.has(state_id): + push_warning("[PropComponent:%s] State not found: %d" % [prop_id, state_id]) + return false + + var next: ReedPropState = _state_map[state_id] + + if _current == next: + return true + + if not next.can_enter(_current, ctx): + if debug_log: + print("[PropComponent:%s] can_enter rejected: %d" % [prop_id, state_id]) + return false + + var from_state_id := get_current_state_id() + var prev := _current + + # ---------- EXIT ---------- + if _current: + _current.on_exit(next, ctx) + + # ---------- SWITCH CURRENT ---------- + _current = next + + # ---------- TRANSITION CHECK ---------- + var transition_handled := false + + if use_trans: + for child in _current.get_children(): + if child is ReedTransition: + if child.can_trigger(prev, ctx): + if debug_log: + print("[PropComponent:%s] Transition triggered: %s" + % [prop_id, child.name]) + + transition_handled = child.execute(prev, _current, ctx) + if transition_handled: + break + + # ---------- ENTER ---------- + if not transition_handled: + _current.on_enter(prev, ctx) + else: + if debug_log: + print("[PropComponent:%s] StateEnter skipped by Transition: %d" + % [prop_id, state_id]) + + if debug_log: + print("[PropComponent:%s] State %d -> %d | ctx=%s" + % [prop_id, from_state_id, state_id, ctx]) + + return true + +## ============================== +## Act Sync Entry +## ============================== +func sync_to_state(state_id: int, act_id: int, instant := false) -> bool: + var ctx := { + "reason": "ACT_SYNC", + "act_id": act_id, + "instant": instant + } + return change_state(state_id, false ,ctx) + +## ============================== +## Editor Tool +## ============================== +func _editor_ensure_states_root() -> void: + var states := get_node_or_null(states_root_name) + if states != null: + return + + states = Node.new() + states.name = states_root_name + add_child(states) + + # ⚠️ 关键:让它成为 Scene 的一部分 + states.owner = get_tree().edited_scene_root + + if debug_log: + print("[PropComponent] Created States root") diff --git a/addons/reedscene/prop/PropComponent.gd.uid b/addons/reedscene/prop/PropComponent.gd.uid new file mode 100644 index 0000000..49a3896 --- /dev/null +++ b/addons/reedscene/prop/PropComponent.gd.uid @@ -0,0 +1 @@ +uid://b4menkyub4ce7 diff --git a/addons/reedscene/prop/PropState.gd b/addons/reedscene/prop/PropState.gd new file mode 100644 index 0000000..0b813ab --- /dev/null +++ b/addons/reedscene/prop/PropState.gd @@ -0,0 +1,56 @@ +@tool +@icon("res://addons/reedscene/prop/icon/prop_state_icon.svg") +class_name ReedPropState extends Node + +##状态编号,默认为-1,-1是不可用编号,请修改 +@export var state_id: int = -1 +##该State的信息是否需要被存入Save中 +@export var save_game: bool = false + +##预装的一些Effect,可以用来对State进行一些初始化 +@export var effects: Array[ReedPropEffect] = [] + +##State的拥有者 +var _owner +##State的prop comp +var _owner_prop_comp + +## 是否已经初始化 +var _inited: bool = false + +##初始化State +func init(owner: Node, prop_comp: Node) -> bool: + # 防止重复初始化 + if _inited: + push_warning("ReedPropState [%s] already initialized." % name) + return false + + if owner == null: + push_error("ReedPropState [%s] init failed: owner is null." % name) + return false + + if prop_comp == null: + push_error("ReedPropState [%s] init failed: prop_comp is null." % name) + return false + + _owner = owner + _owner_prop_comp = prop_comp + _inited = true + return true + +##是否可以进入此状态,默认为真 +func can_enter(_current: ReedPropState, _ctx: Dictionary) -> bool: + return true + +##State进入 +func on_enter(_from: ReedPropState, _ctx: Dictionary) -> void: + if not _inited: + push_error("ReedPropState [%s] entered before init!" % name) + return + + for e in effects: + e.apply(_owner, _owner_prop_comp, _ctx) + +##State退出 +func on_exit(_to: ReedPropState, _ctx: Dictionary) -> void: + pass diff --git a/addons/reedscene/prop/PropState.gd.uid b/addons/reedscene/prop/PropState.gd.uid new file mode 100644 index 0000000..3382336 --- /dev/null +++ b/addons/reedscene/prop/PropState.gd.uid @@ -0,0 +1 @@ +uid://7lml6d1t5xtq diff --git a/addons/reedscene/prop/ReedPropEffect.gd b/addons/reedscene/prop/ReedPropEffect.gd new file mode 100644 index 0000000..bf92baf --- /dev/null +++ b/addons/reedscene/prop/ReedPropEffect.gd @@ -0,0 +1,62 @@ +''' 此Resource定义了一系列的Prop可能需要的预设的简单Effect,如果有更复杂的需求,应该重写State的OnEnter +''' +@tool +@icon("uid://cw1yyc4oeph85") +extends Resource +class_name ReedPropEffect + +enum TargetType { + OWNER, + NODE_PATH +} + +enum EffectType { + SET_VALUE, + CALL_FUNC +} + +##作用目标的类型,默认为PropComp的拥有者 +@export var target_type: TargetType = TargetType.OWNER +##如果选择了NodePath,则会读取此字段,默认不读取 +@export var target_path: NodePath +##作用的具体效果类别,默认为设置某个数值 +@export var effect_type: EffectType = EffectType.SET_VALUE + +## SetValue 用 +@export var property_name: StringName +@export var value: Variant + +## CallFunc 用 +@export var func_name: StringName +@export var func_args: Array[Variant] = [] + +## 是否在退出 state 时恢复 +@export var restore_on_exit: bool = false + +## 运行时缓存 +var _cached_old_value: Variant + +##应用效果 +func apply(owner: Node, prop_comp: Node, ctx: Dictionary) -> void: + var target := _resolve_target(owner, prop_comp) + if target == null: + return + + match effect_type: + EffectType.SET_VALUE: + # 你也可以加 has_property 检查,但 Godot 没有统一 API,这里先直接 set + target.set(property_name, value) + + EffectType.CALL_FUNC: + if target.has_method(func_name): + target.callv(func_name, func_args) + +##获取到组件或对象 +func _resolve_target(owner: Node, prop_comp: Node) -> Object: + match target_type: + TargetType.OWNER: + return owner + TargetType.NODE_PATH: + if owner: + return owner.get_node_or_null(target_path) + return null diff --git a/addons/reedscene/prop/ReedPropEffect.gd.uid b/addons/reedscene/prop/ReedPropEffect.gd.uid new file mode 100644 index 0000000..7cb8ce5 --- /dev/null +++ b/addons/reedscene/prop/ReedPropEffect.gd.uid @@ -0,0 +1 @@ +uid://cdvgq0xqdbagk diff --git a/addons/reedscene/prop/ReedTransition.gd b/addons/reedscene/prop/ReedTransition.gd new file mode 100644 index 0000000..2b16bfe --- /dev/null +++ b/addons/reedscene/prop/ReedTransition.gd @@ -0,0 +1,36 @@ +@tool +@icon("res://addons/reedscene/prop/icon/prop_trans_icon.svg") + +extends Node +class_name ReedTransition + +@export var from_state_id: int = -1 +@export var effects: Array[ReedPropEffect] = [] + +## runtime only +@export var runtime_only: bool = true + +##Transtion能否被触发 +func can_trigger(from: ReedPropState, ctx: Dictionary) -> bool: + if from == null: + return false + + if from_state_id != -1 and from.state_id != from_state_id: + return false + + if runtime_only and ctx.get("is_load", false): + return false + + return true + + +##执行Transition的逻辑 +func execute(from: ReedPropState, to: ReedPropState, ctx: Dictionary) -> bool: + # Effect 不需要知道 from/to,但 Transition 需要用 to 拿目标对象 + var owner : Node= to._owner + var prop_comp : Node= to._owner_prop_comp + + for e in effects: + e.apply(owner, prop_comp, ctx) + + return true diff --git a/addons/reedscene/prop/ReedTransition.gd.uid b/addons/reedscene/prop/ReedTransition.gd.uid new file mode 100644 index 0000000..578676c --- /dev/null +++ b/addons/reedscene/prop/ReedTransition.gd.uid @@ -0,0 +1 @@ +uid://jeybblac0kg2 diff --git a/addons/reedscene/prop/icon/prop_effect_icon.svg b/addons/reedscene/prop/icon/prop_effect_icon.svg new file mode 100644 index 0000000..5361c2e --- /dev/null +++ b/addons/reedscene/prop/icon/prop_effect_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/addons/reedscene/prop/icon/prop_effect_icon.svg.import b/addons/reedscene/prop/icon/prop_effect_icon.svg.import new file mode 100644 index 0000000..0008f4d --- /dev/null +++ b/addons/reedscene/prop/icon/prop_effect_icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cw1yyc4oeph85" +path="res://.godot/imported/prop_effect_icon.svg-8b989d7af0a50d984a55fda3d5d49014.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/reedscene/prop/icon/prop_effect_icon.svg" +dest_files=["res://.godot/imported/prop_effect_icon.svg-8b989d7af0a50d984a55fda3d5d49014.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/reedscene/prop/icon/prop_icon.svg b/addons/reedscene/prop/icon/prop_icon.svg new file mode 100644 index 0000000..e4df5fe --- /dev/null +++ b/addons/reedscene/prop/icon/prop_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/addons/reedscene/prop/icon/prop_icon.svg.import b/addons/reedscene/prop/icon/prop_icon.svg.import new file mode 100644 index 0000000..42f0a1a --- /dev/null +++ b/addons/reedscene/prop/icon/prop_icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dsxo2ukbb0g45" +path="res://.godot/imported/prop_icon.svg-4813df6b5b1ef2c0b427ea393d13fa6f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/reedscene/prop/icon/prop_icon.svg" +dest_files=["res://.godot/imported/prop_icon.svg-4813df6b5b1ef2c0b427ea393d13fa6f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/reedscene/prop/icon/prop_state_icon.svg b/addons/reedscene/prop/icon/prop_state_icon.svg new file mode 100644 index 0000000..a2759d9 --- /dev/null +++ b/addons/reedscene/prop/icon/prop_state_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/addons/reedscene/prop/icon/prop_state_icon.svg.import b/addons/reedscene/prop/icon/prop_state_icon.svg.import new file mode 100644 index 0000000..435e5ea --- /dev/null +++ b/addons/reedscene/prop/icon/prop_state_icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dursmjgc7ug8f" +path="res://.godot/imported/prop_state_icon.svg-c74620cdc425f868535286f7ce62d08d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/reedscene/prop/icon/prop_state_icon.svg" +dest_files=["res://.godot/imported/prop_state_icon.svg-c74620cdc425f868535286f7ce62d08d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/reedscene/prop/icon/prop_trans_icon.svg b/addons/reedscene/prop/icon/prop_trans_icon.svg new file mode 100644 index 0000000..e8aa8ed --- /dev/null +++ b/addons/reedscene/prop/icon/prop_trans_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/addons/reedscene/prop/icon/prop_trans_icon.svg.import b/addons/reedscene/prop/icon/prop_trans_icon.svg.import new file mode 100644 index 0000000..952291c --- /dev/null +++ b/addons/reedscene/prop/icon/prop_trans_icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c2hji2jfaditq" +path="res://.godot/imported/prop_trans_icon.svg-427c5d6c6dfbea98cf99a23374b74151.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/reedscene/prop/icon/prop_trans_icon.svg" +dest_files=["res://.godot/imported/prop_trans_icon.svg-427c5d6c6dfbea98cf99a23374b74151.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/reedscene/reedscene.gd b/addons/reedscene/reedscene.gd index 8ecc6d4..5af87f6 100644 --- a/addons/reedscene/reedscene.gd +++ b/addons/reedscene/reedscene.gd @@ -1,22 +1,2 @@ @tool extends EditorPlugin - - -func _enable_plugin() -> void: - # Add autoloads here. - pass - - -func _disable_plugin() -> void: - # Remove autoloads here. - pass - - -func _enter_tree() -> void: - # Initialization of the plugin goes here. - pass - - -func _exit_tree() -> void: - # Clean-up of the plugin goes here. - pass diff --git a/addons/reedscene/scene/ReedScene.gd b/addons/reedscene/scene/ReedScene.gd index ae59d72..2ec6487 100644 --- a/addons/reedscene/scene/ReedScene.gd +++ b/addons/reedscene/scene/ReedScene.gd @@ -25,4 +25,127 @@ 对于Scene,Scene通过PropComponent上的ID,通过ID获取到PropComponent所挂载的组件,这也是为什么我强制要求 PropComponent必须是处于Prop的最上层子节点集。 ''' + class_name ReedScene extends Node2D + +## ============================== +## Export Config +## ============================== +@export var props_root_path: NodePath = ^"Props" +@export var auto_attach_prop_component := true +@export var debug_log := true + +## ============================== +## Internal State +## ============================== + +var _act_manager: ActManager +var _props_root: Node +var _prop_map: Dictionary = {} # prop_id -> PropComponent + +## ============================== +## Lifecycle +## ============================== +func _enter_tree() -> void: + if Engine.is_editor_hint(): + _editor_auto_attach_prop_components() + +## ============================== +## Resolve References +## ============================== +func _resolve_act_manager() -> void: + _act_manager = get_node_or_null("ActManager") + if _act_manager == null: + push_error("[ReedScene] ActManager not found.") + return + +func _resolve_props_root() -> void: + _props_root = get_node_or_null(props_root_path) + if _props_root == null: + push_error("[ReedScene] Props root not found: %s" % props_root_path) + +## ============================== +## Prop Collection +## ============================== + +func _collect_props() -> void: + _prop_map.clear() + + if _props_root == null: + return + + for prop in _props_root.get_children(): + if not prop is Node: + continue + + var prop_comp := _find_prop_component(prop) + if prop_comp == null: + continue + + var prop_id := prop_comp.prop_id + if prop_id < 0: + push_warning("[ReedScene] Prop has invaild ID: %s" % prop.name) + continue + + if _prop_map.has(prop_id): + push_error("[ReedScene] Duplicate Prop ID: %s" % prop_id) + continue + + _prop_map[prop_id] = prop_comp + + if debug_log: + print("[ReedScene] Registered Prop:", prop_id) + +func _find_prop_component(prop: Node) -> PropComponent: + for child in prop.get_children(): + if child is PropComponent: + return child + return null + +## ============================== +## Act Binding +## ============================== +func _bind_act_events() -> void: + if _act_manager == null: + return + + _act_manager.act_changed.connect(_on_act_changed) + + +func _on_act_changed(from_act: StringName, to_act: StringName) -> void: + if debug_log: + print("[ReedScene] Act changed:", from_act, "->", to_act) + + for prop_comp in _prop_map.values(): + prop_comp.on_act_changed(from_act, to_act) + +## ============================== +## Editor Helpers +## ============================== +func _editor_auto_attach_prop_components() -> void: + if not auto_attach_prop_component: + return + + var props_root := get_node_or_null(props_root_path) + if props_root == null: + return + + for prop in props_root.get_children(): + if not prop is Node: + continue + + if _find_prop_component(prop) != null: + continue + + var comp := PropComponent.new() + prop.add_child(comp) + comp.owner = get_tree().edited_scene_root + + if debug_log: + print("[ReedScene][Editor] Auto attached PropComponent to:", prop.name) + +func _ready() -> void: + _resolve_act_manager() + _resolve_props_root() + _collect_props() + _bind_act_events() diff --git a/update.md b/update.md index b26d641..537fd1b 100644 --- a/update.md +++ b/update.md @@ -27,7 +27,10 @@ v0.2.2 - 添加了落石的基础类,可以实现,开始抖动,结束抖动,移动,结束移动,移动到目标点等一系列操作 - 添加了一个落石的基础案例,可以在此案例的基础上对落石功能进行拓展和修改 +v0.2.3 +- 基础的关卡编辑器,主要明确了几个概念:Prop Scene,Act,目前已经有了一个基础的展示功能性质的Demo +- 分离了Player和控制器,现在Player是Avatar,控制器是PlayerController,控制器向玩家发送指令,玩家接收指令以驱动功能。 ## 更新计划 @@ -59,17 +62,17 @@ V0.2 主要是实现蔚蓝的地图相关的功能,比如穿过一个入口之后时间缓速并切换场景,等 - [x] Phantom Camera 插件接入 -- [ ] 相机功能 - - [ ] 相机追随 - - [ ] 相机震动 +- [ ] ~~相机功能~~ + - [x] ~~相机追随~~ + - [ ] ~~相机震动~~ - [ ] 地图功能 - - [ ] 地图美术功能 - - [ ] 地图物件功能 - - [ ] 落石 - - [ ] 移动跟随平台 -- [ ] 玩家死亡和重生的逻辑 -- [ ] Room功能:一个Level由n个Room组成,Room存在一个Entrance,玩家进入Entrance会让Entrance向上传输消息给Room并让镜头切换到对应的Room - - [ ] entrance的对应不同的复活点,从不同的entrance进入会让玩家死亡后在不同的复活点复活 + - [ ] ~~地图美术功能~~ + - [ ] ~~地图物件功能~~ + - [ ] 关卡编辑器 + - [x] 根据state的物件性质加载 + - [ ] 物件性质预设集Act + - [ ] 场景管理器SceneManager + - [ ] 玩家死亡和重生点 V0.3