From 448c2f352abfba44c65e4944ac31936bae827759 Mon Sep 17 00:00:00 2001 From: vaporvee Date: Fri, 19 Jan 2024 22:17:44 +0100 Subject: [PATCH] i dont even remember --- addons/destruction/destruction.gd | 100 ++++++++++++++++++ addons/destruction/destruction_icon.svg | 94 ++++++++++++++++ .../destruction/destruction_icon.svg.import | 37 +++++++ .../destruction_icon.svg.import.license | 4 + .../destruction/destruction_icon.svg.license | 4 + addons/destruction/plugin.cfg | 11 ++ addons/destruction/plugin.gd | 6 ++ addons/destruction/shard.tscn.license | 3 + cube/cube_fragments.glb | Bin 0 -> 21664 bytes cube/cube_fragments.glb.import | 41 +++++++ cube/cube_fragments.tscn | 5 + cube/destructible_cube.tscn | 25 +++++ cube/destructible_cube.tscn.license | 4 + cube/fractured_cube.glb.import.license | 4 + cube/fractured_cube.glb.license | 4 + cube/marble.tres | 6 ++ cube/marble.tres.license | 4 + cube/marble_albedo.jpg | Bin 0 -> 28997 bytes cube/marble_albedo.jpg.import | 35 ++++++ cube/marble_albedo.jpg.import.license | 4 + cube/marble_albedo.jpg.license | 3 + demo.gd | 23 ++++ demo.tscn | 63 +++++++++++ project.godot | 19 ++++ scenes/completion_counter.tscn | 2 +- scenes/gravity_gun.tscn | 71 ++++++++++--- scenes/levels/debug.tscn | 4 +- scenes/player.tscn | 2 - scripts/completion_counter.gd | 25 +++-- scripts/gravity_gun.gd | 6 ++ .../interactables/completer/button_stand.gd | 5 +- .../interactables/completer/completer_base.gd | 14 +-- 32 files changed, 596 insertions(+), 32 deletions(-) create mode 100644 addons/destruction/destruction.gd create mode 100644 addons/destruction/destruction_icon.svg create mode 100644 addons/destruction/destruction_icon.svg.import create mode 100644 addons/destruction/destruction_icon.svg.import.license create mode 100644 addons/destruction/destruction_icon.svg.license create mode 100644 addons/destruction/plugin.cfg create mode 100644 addons/destruction/plugin.gd create mode 100644 addons/destruction/shard.tscn.license create mode 100644 cube/cube_fragments.glb create mode 100644 cube/cube_fragments.glb.import create mode 100644 cube/cube_fragments.tscn create mode 100644 cube/destructible_cube.tscn create mode 100644 cube/destructible_cube.tscn.license create mode 100644 cube/fractured_cube.glb.import.license create mode 100644 cube/fractured_cube.glb.license create mode 100644 cube/marble.tres create mode 100644 cube/marble.tres.license create mode 100644 cube/marble_albedo.jpg create mode 100644 cube/marble_albedo.jpg.import create mode 100644 cube/marble_albedo.jpg.import.license create mode 100644 cube/marble_albedo.jpg.license create mode 100644 demo.gd create mode 100644 demo.tscn create mode 100644 scripts/gravity_gun.gd diff --git a/addons/destruction/destruction.gd b/addons/destruction/destruction.gd new file mode 100644 index 0000000..d99380b --- /dev/null +++ b/addons/destruction/destruction.gd @@ -0,0 +1,100 @@ +# SPDX-FileCopyrightText: 2023 Jummit +# +# SPDX-License-Identifier: MIT + +@tool +@icon("destruction_icon.svg") +class_name Destruction +extends Node + +## Handles destruction of the parent node. +## +## When [method destroy] is called, the parent node is freed and shards +## are added to the [member shard_container]. + +## A scene of the fragmented mesh containing multiple [MeshInstance3D]s. +@export var fragmented: PackedScene: set = set_fragmented +## The node where created shards are added to. +@onready @export var shard_container := get_node("../../") + +@export_group("Animation") +## How many seconds until the shards fade away. Set to -1 to disable fading. +@export var fade_delay := 2.0 +## How many seconds until the shards shrink. Set to -1 to disable shrinking. +@export var shrink_delay := 2.0 +## How long the animation lasts before the shard is removed. +@export var animation_length := 2.0 + +@export_group("Collision") +## The [member RigidBody3D.collision_layer] set on the created shards. +@export_flags_3d_physics var collision_layer = 1 +## The [member RigidBody3D.collision_mask] set on the created shards. +@export_flags_3d_physics var collision_mask = 1 + +## Cached shard meshes (instantiated from [member fragmented]). +static var cached_meshes := {} +## Cached collision shapes. +static var cached_shapes := {} + +## Remove the parent node and add shards to the shard container. +func destroy(explosion_power := 1.0) -> void: + if not fragmented in cached_meshes: + cached_meshes[fragmented] = fragmented.instantiate() + for shard_mesh in cached_meshes[fragmented].get_children(): + cached_shapes[shard_mesh] = shard_mesh.mesh.create_convex_shape() + var original_meshes = cached_meshes[fragmented] + for original in original_meshes.get_children(): + if original is MeshInstance3D: + _add_shard(original, explosion_power) + get_parent().queue_free() + + +func _add_shard(original: MeshInstance3D, explosion_power: float) -> void: + var body := RigidBody3D.new() + var mesh := MeshInstance3D.new() + var shape := CollisionShape3D.new() + body.add_child(mesh) + body.add_child(shape) + shard_container.add_child(body, true) + body.global_position = get_parent().global_transform.origin + original.position + body.collision_layer = collision_layer + body.collision_mask = collision_mask + shape.shape = cached_shapes[original] + mesh.mesh = original.mesh + if fade_delay >= 0: + var material = original.mesh.surface_get_material(0) + if material is StandardMaterial3D: + material = material.duplicate() + material.flags_transparent = true + get_tree().create_tween().tween_property(material, "albedo_color", + Color(1, 1, 1, 0), animation_length)\ + .set_delay(fade_delay)\ + .set_trans(Tween.TRANS_EXPO)\ + .set_ease(Tween.EASE_OUT) + mesh.material_override = material + else: + push_warning("Shard doesn't use a StandardMaterial3D, can't add transparency.") + body.apply_impulse(_random_direction() * explosion_power, + -original.position.normalized()) + if shrink_delay < 0 and fade_delay < 0: + get_tree().create_timer(animation_length)\ + .timeout.connect(func(): body.queue_free()) + elif shrink_delay >= 0: + var tween := get_tree().create_tween() + tween.tween_property(mesh, "scale", Vector3.ZERO, animation_length)\ + .set_delay(shrink_delay) + tween.finished.connect(func(): body.queue_free()) + + +func set_fragmented(to: PackedScene) -> void: + fragmented = to + if is_inside_tree(): + get_tree().node_configuration_warning_changed.emit(self) + + +func _get_configuration_warnings() -> PackedStringArray: + return ["No fragmented version set"] if not fragmented else [] + + +static func _random_direction() -> Vector3: + return (Vector3(randf(), randf(), randf()) - Vector3.ONE / 2.0).normalized() * 2.0 diff --git a/addons/destruction/destruction_icon.svg b/addons/destruction/destruction_icon.svg new file mode 100644 index 0000000..b0584d9 --- /dev/null +++ b/addons/destruction/destruction_icon.svg @@ -0,0 +1,94 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/addons/destruction/destruction_icon.svg.import b/addons/destruction/destruction_icon.svg.import new file mode 100644 index 0000000..1b267c1 --- /dev/null +++ b/addons/destruction/destruction_icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://co3om28rgeos3" +path="res://.godot/imported/destruction_icon.svg-716fc5b182e74f5a75cf299975d03542.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/destruction/destruction_icon.svg" +dest_files=["res://.godot/imported/destruction_icon.svg-716fc5b182e74f5a75cf299975d03542.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/destruction/destruction_icon.svg.import.license b/addons/destruction/destruction_icon.svg.import.license new file mode 100644 index 0000000..26e9709 --- /dev/null +++ b/addons/destruction/destruction_icon.svg.import.license @@ -0,0 +1,4 @@ +SPDX-FileCopyrightText: 2023 Jummit +SPDX-FileContributor: Jummit + +SPDX-License-Identifier: CC0-1.0 diff --git a/addons/destruction/destruction_icon.svg.license b/addons/destruction/destruction_icon.svg.license new file mode 100644 index 0000000..26e9709 --- /dev/null +++ b/addons/destruction/destruction_icon.svg.license @@ -0,0 +1,4 @@ +SPDX-FileCopyrightText: 2023 Jummit +SPDX-FileContributor: Jummit + +SPDX-License-Identifier: CC0-1.0 diff --git a/addons/destruction/plugin.cfg b/addons/destruction/plugin.cfg new file mode 100644 index 0000000..783667d --- /dev/null +++ b/addons/destruction/plugin.cfg @@ -0,0 +1,11 @@ +; SPDX-FileCopyrightText: 2023 Jummit +; +; SPDX-License-Identifier: MIT + +[plugin] + +name="Destruction" +description="Destroy 3D objects." +author="Jummit" +version="7.0" +script="plugin.gd" diff --git a/addons/destruction/plugin.gd b/addons/destruction/plugin.gd new file mode 100644 index 0000000..d7925f3 --- /dev/null +++ b/addons/destruction/plugin.gd @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: 2023 Jummit +# +# SPDX-License-Identifier: MIT + +@tool +extends EditorPlugin diff --git a/addons/destruction/shard.tscn.license b/addons/destruction/shard.tscn.license new file mode 100644 index 0000000..74ad372 --- /dev/null +++ b/addons/destruction/shard.tscn.license @@ -0,0 +1,3 @@ +# SPDX-FileCopyrightText: 2023 Jummit +# +# SPDX-License-Identifier: MIT diff --git a/cube/cube_fragments.glb b/cube/cube_fragments.glb new file mode 100644 index 0000000000000000000000000000000000000000..40b3a9e6f36087bd8e5f6da37d2dd2aa8f3d85fa GIT binary patch literal 21664 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 YELe1p_`?7mzC+3Hqp7&T void: + _destruction.destroy(5) + _destroy_button.disabled = true + await get_tree().create_timer(1).timeout + var new := _destructible_cube_scene.instantiate() + add_child(new) + _destruction = new.get_node("Destruction") + _destroy_button.disabled = false diff --git a/demo.tscn b/demo.tscn new file mode 100644 index 0000000..a89adea --- /dev/null +++ b/demo.tscn @@ -0,0 +1,63 @@ +[gd_scene load_steps=8 format=3 uid="uid://dkgkgrq6507kj"] + +[ext_resource type="Script" path="res://demo.gd" id="1_xvv5r"] +[ext_resource type="PackedScene" uid="uid://cexof5tlc7l1i" path="res://cube/destructible_cube.tscn" id="2_1ot51"] + +[sub_resource type="BoxMesh" id="BoxMesh_yig7p"] +size = Vector3(20, 0.5, 20) + +[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_dirmc"] +data = PackedVector3Array(-10, 0.25, 10, 10, 0.25, 10, -10, -0.25, 10, 10, 0.25, 10, 10, -0.25, 10, -10, -0.25, 10, 10, 0.25, -10, -10, 0.25, -10, 10, -0.25, -10, -10, 0.25, -10, -10, -0.25, -10, 10, -0.25, -10, 10, 0.25, 10, 10, 0.25, -10, 10, -0.25, 10, 10, 0.25, -10, 10, -0.25, -10, 10, -0.25, 10, -10, 0.25, -10, -10, 0.25, 10, -10, -0.25, -10, -10, 0.25, 10, -10, -0.25, 10, -10, -0.25, -10, 10, 0.25, 10, -10, 0.25, 10, 10, 0.25, -10, -10, 0.25, 10, -10, 0.25, -10, 10, 0.25, -10, -10, -0.25, 10, 10, -0.25, 10, -10, -0.25, -10, 10, -0.25, 10, 10, -0.25, -10, -10, -0.25, -10) + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_d8soj"] +sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) +ground_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) + +[sub_resource type="Sky" id="Sky_mukl1"] +sky_material = SubResource("ProceduralSkyMaterial_d8soj") + +[sub_resource type="Environment" id="Environment_hh15e"] +background_mode = 2 +sky = SubResource("Sky_mukl1") +tonemap_mode = 2 + +[node name="Demo" type="Node3D"] +script = ExtResource("1_xvv5r") + +[node name="DestructibleCube" parent="." instance=ExtResource("2_1ot51")] +editor_description = "The cube is replaced with a new instance once destroyed." +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.49026, -2) + +[node name="Floor" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.759737, 0) +mesh = SubResource("BoxMesh_yig7p") + +[node name="StaticBody3D" type="StaticBody3D" parent="Floor"] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Floor/StaticBody3D"] +shape = SubResource("ConcavePolygonShape3D_dirmc") + +[node name="Camera3D" type="Camera3D" parent="."] +transform = Transform3D(0.680694, 0.293844, -0.671052, 0, 0.916027, 0.401115, 0.732567, -0.273037, 0.623535, -5.55537, 3.32067, 5.16199) + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(-0.866023, -0.433016, 0.250001, 0, 0.499998, 0.866027, -0.500003, 0.749999, -0.43301, 0, 0, 0) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_hh15e") + +[node name="DestroyButton" type="Button" parent="."] +anchors_preset = 7 +anchor_left = 0.5 +anchor_top = 1.0 +anchor_right = 0.5 +anchor_bottom = 1.0 +offset_left = -84.5 +offset_top = -97.0 +offset_right = 84.5 +offset_bottom = -21.0 +grow_horizontal = 2 +grow_vertical = 0 +text = "Destroy" + +[connection signal="pressed" from="DestroyButton" to="." method="_on_destroy_button_pressed"] diff --git a/project.godot b/project.godot index 7afc06d..a44a45c 100644 --- a/project.godot +++ b/project.godot @@ -23,6 +23,10 @@ boot_splash/show_image.editor=true window/stretch/mode="canvas_items" +[editor_plugins] + +enabled=PackedStringArray("res://addons/destruction/plugin.cfg") + [input] move_left={ @@ -65,8 +69,23 @@ 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":69,"key_label":0,"unicode":101,"echo":false,"script":null) ] } +gravity_activate={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":16,"position":Vector2(142, 11),"global_position":Vector2(146, 52),"factor":1.0,"button_index":5,"canceled":false,"pressed":true,"double_click":false,"script":null) +, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(337, 22),"global_position":Vector2(341, 63),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} +gravity_change={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(338, 10),"global_position":Vector2(342, 51),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} [rendering] +anti_aliasing/quality/msaa_3d=1 +anti_aliasing/quality/screen_space_aa=1 +anti_aliasing/quality/use_taa=true +anti_aliasing/quality/use_debanding=true environment/defaults/default_environment="res://resources/environment.tres" environment/defaults/default_clear_color.release=Color(0, 0, 0, 1) diff --git a/scenes/completion_counter.tscn b/scenes/completion_counter.tscn index 3ce34a3..4c99006 100644 --- a/scenes/completion_counter.tscn +++ b/scenes/completion_counter.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=3 format=3 uid="uid://6njtmij7sikl"] +[gd_scene load_steps=3 format=3 uid="uid://22blfybi6n4q"] [ext_resource type="Script" path="res://scripts/completion_counter.gd" id="1_40xge"] diff --git a/scenes/gravity_gun.tscn b/scenes/gravity_gun.tscn index 6a90ed6..0bc0c67 100644 --- a/scenes/gravity_gun.tscn +++ b/scenes/gravity_gun.tscn @@ -1,5 +1,6 @@ -[gd_scene load_steps=15 format=3 uid="uid://cl6gw3huejnrl"] +[gd_scene load_steps=21 format=3 uid="uid://cl6gw3huejnrl"] +[ext_resource type="Script" path="res://scripts/gravity_gun.gd" id="1_0upyy"] [ext_resource type="ArrayMesh" uid="uid://cxw30fmp15jsd" path="res://models/gun.obj" id="1_803cf"] [ext_resource type="Environment" uid="uid://drn5fwa4uhv4m" path="res://resources/environment.tres" id="1_vtn44"] [ext_resource type="Material" uid="uid://b6r8e4302xg1d" path="res://assets/materials/dark_metal.material" id="2_qrl87"] @@ -10,9 +11,16 @@ [ext_resource type="Material" uid="uid://c8bic1or51fbf" path="res://assets/materials/old_plastic.material" id="7_c1s4a"] [ext_resource type="Texture2D" uid="uid://b4en3dw3q324p" path="res://assets/textures/circle.png" id="8_al3c7"] -[sub_resource type="World3D" id="World3D_6qira"] +[sub_resource type="World3D" id="World3D_wp4pn"] environment = ExtResource("1_vtn44") +[sub_resource type="GDScript" id="GDScript_sr7lp"] +script/source = "extends SubViewport + +func _ready() -> void: + msaa_3d = ProjectSettings.get_setting(\"rendering/anti_aliasing/quality/msaa_3d\",0) +" + [sub_resource type="ShaderMaterial" id="ShaderMaterial_twwch"] render_priority = 0 shader = ExtResource("3_aeppb") @@ -33,7 +41,7 @@ scale_max = 0.07 collision_mode = 2 collision_use_scale = true -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_y24ld"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_rnipw"] transparency = 2 alpha_scissor_threshold = 0.9 alpha_antialiasing_mode = 0 @@ -45,30 +53,58 @@ billboard_mode = 1 billboard_keep_scale = true [sub_resource type="QuadMesh" id="QuadMesh_wtlns"] -material = SubResource("StandardMaterial3D_y24ld") +material = SubResource("StandardMaterial3D_rnipw") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_5ccgj"] +direction = Vector3(3, 0, 1) +initial_velocity_min = 10.0 +initial_velocity_max = 10.0 + +[sub_resource type="Curve" id="Curve_xucvk"] +_data = [Vector2(0.0245902, 0), 0.0, 1.4, 0, 0, Vector2(0.172131, 0), 1.65004, 0.0, 0, 0] +point_count = 2 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_endjk"] +emission_enabled = true +emission = Color(0, 1, 1, 1) +emission_energy_multiplier = 16.0 +backlight = Color(1, 1, 1, 1) +billboard_keep_scale = true +point_size = 12.7 +use_particle_trails = true + +[sub_resource type="RibbonTrailMesh" id="RibbonTrailMesh_fwaab"] +material = SubResource("StandardMaterial3D_endjk") +size = 12.0 +section_length = 0.3 +section_segments = 2 +curve = SubResource("Curve_xucvk") [node name="GravityGun" type="CanvasLayer"] follow_viewport_enabled = true +script = ExtResource("1_0upyy") [node name="SubViewportContainer" type="SubViewportContainer" parent="."] -anchors_preset = 12 -anchor_top = 1.0 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -offset_top = -324.0 grow_horizontal = 2 -grow_vertical = 0 -stretch_shrink = 2 -metadata/_edit_use_anchors_ = true +grow_vertical = 2 +size_flags_horizontal = 0 +size_flags_vertical = 0 +stretch = true [node name="SubViewport" type="SubViewport" parent="SubViewportContainer"] -world_3d = SubResource("World3D_6qira") +own_world_3d = true +world_3d = SubResource("World3D_wp4pn") transparent_bg = true handle_input_locally = false -gui_embed_subwindows = true +scaling_3d_scale = 2.0 +sdf_scale = 0 size = Vector2i(1152, 648) size_2d_override_stretch = true render_target_update_mode = 4 +script = SubResource("GDScript_sr7lp") [node name="Node3D" type="Node3D" parent="SubViewportContainer/SubViewport"] @@ -119,3 +155,14 @@ draw_pass_1 = SubResource("QuadMesh_wtlns") [node name="GPUParticlesCollisionBox3D" type="GPUParticlesCollisionBox3D" parent="SubViewportContainer/SubViewport/Node3D/Camera3D/MeshInstance3D"] transform = Transform3D(0.999923, -0.012392, 0.000616441, 0.0123854, 0.999875, 0.00980631, -0.000737865, -0.00979792, 0.999952, 0.358337, 0.108517, -0.0012207) size = Vector3(1.17664, 0.301201, 0.299805) + +[node name="GravityParticles" type="GPUParticles3D" parent="SubViewportContainer/SubViewport/Node3D/Camera3D/MeshInstance3D"] +transform = Transform3D(1, -2.79397e-08, 8.70349e-09, 1.9744e-07, 1, 5.83791e-08, -7.93013e-09, -5.67382e-07, 1, 1, 0.1, 0) +visible = false +amount = 20 +lifetime = 0.1 +visibility_aabb = AABB(0.0726342, 0.335538, 0.399176, 0.593013, 0.887273, 1.34056) +trail_enabled = true +trail_lifetime = 0.8 +process_material = SubResource("ParticleProcessMaterial_5ccgj") +draw_pass_1 = SubResource("RibbonTrailMesh_fwaab") diff --git a/scenes/levels/debug.tscn b/scenes/levels/debug.tscn index 007be02..074e284 100644 --- a/scenes/levels/debug.tscn +++ b/scenes/levels/debug.tscn @@ -4,7 +4,7 @@ [ext_resource type="PackedScene" uid="uid://ddwkhfly2xyyt" path="res://models/interior.obj" id="1_lphcl"] [ext_resource type="PackedScene" uid="uid://b8bvidqu7tmfs" path="res://scenes/objects/interactables/task_terminal.tscn" id="3_30m3x"] [ext_resource type="PackedScene" uid="uid://dqy8bqf1chm8c" path="res://scenes/objects/interactables/button_stand.tscn" id="4_cruoa"] -[ext_resource type="PackedScene" uid="uid://6njtmij7sikl" path="res://scenes/completion_counter.tscn" id="5_lo1l3"] +[ext_resource type="PackedScene" uid="uid://22blfybi6n4q" path="res://scenes/completion_counter.tscn" id="5_lo1l3"] [ext_resource type="PackedScene" uid="uid://cy0x2nliyw8gw" path="res://scenes/door.tscn" id="6_853p2"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_780x3"] @@ -39,6 +39,7 @@ transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0.5, 0 [node name="ButtonStand" parent="." instance=ExtResource("4_cruoa")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0.7, 0) +one_shot = true [node name="CompletionCounter" parent="." node_paths=PackedStringArray("nodes_needed") instance=ExtResource("5_lo1l3")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0617981, 3.05379, 6.24098) @@ -50,6 +51,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.1, 1.425, 6.64) [node name="ButtonStand2" parent="." instance=ExtResource("4_cruoa")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0.7, 4) +[connection signal="lock" from="CompletionCounter" to="Door" method="close"] [connection signal="unlock" from="CompletionCounter" to="Door" method="open"] [editable path="interior"] diff --git a/scenes/player.tscn b/scenes/player.tscn index cd30638..bc8dea2 100644 --- a/scenes/player.tscn +++ b/scenes/player.tscn @@ -39,5 +39,3 @@ mesh = SubResource("QuadMesh_dicpk") script = ExtResource("2_jg7te") [node name="GravityGun" parent="." instance=ExtResource("2_ahuce")] - -[editable path="GravityGun"] diff --git a/scripts/completion_counter.gd b/scripts/completion_counter.gd index 4a54da0..9b96553 100644 --- a/scripts/completion_counter.gd +++ b/scripts/completion_counter.gd @@ -1,19 +1,28 @@ extends Node signal unlock +signal lock @export var nodes_needed: Array[Completer] -var uncompleted: int + +var unlocked: bool func _ready(): - uncompleted = nodes_needed.size() for node in nodes_needed: - node.completed.connect(complete) + node.triggered.connect(complete) func complete(): - uncompleted -= 1 - if uncompleted == 0: - unlock.emit() + if areAllNodesUnlocked(): + if !unlocked: + unlock.emit() + unlocked = true + else: + if unlocked: + lock.emit() + unlocked = false -func uncomplete(): - pass #TODO +func areAllNodesUnlocked(): + for node in nodes_needed: + if !node.completed: + return false + return true diff --git a/scripts/gravity_gun.gd b/scripts/gravity_gun.gd new file mode 100644 index 0000000..10c19a3 --- /dev/null +++ b/scripts/gravity_gun.gd @@ -0,0 +1,6 @@ +extends CanvasLayer + +@onready var gravity_particles: GPUParticles3D = $SubViewportContainer/SubViewport/Node3D/Camera3D/MeshInstance3D/GravityParticles + +func _process(_delta: float) -> void: + gravity_particles.visible = Input.is_action_pressed("gravity_activate") diff --git a/scripts/interactables/completer/button_stand.gd b/scripts/interactables/completer/button_stand.gd index 94f27f4..e529396 100644 --- a/scripts/interactables/completer/button_stand.gd +++ b/scripts/interactables/completer/button_stand.gd @@ -4,4 +4,7 @@ extends Completer func _on_interaction_area_interacted(): animation_player.play("press") - super.toggle_complete() + toggle_complete() + if one_shot: + await animation_player.animation_finished + $Button.hide() diff --git a/scripts/interactables/completer/completer_base.gd b/scripts/interactables/completer/completer_base.gd index a708079..3a8168c 100644 --- a/scripts/interactables/completer/completer_base.gd +++ b/scripts/interactables/completer/completer_base.gd @@ -1,16 +1,16 @@ +@tool extends Node class_name Completer @export var one_shot: bool -signal completed -signal uncompleted +signal triggered -var toggle: bool = true +var completed: bool func toggle_complete(): - toggle = !toggle - if one_shot || toggle: - completed.emit() + if one_shot: + completed = true else: - uncompleted.emit() + completed = !completed + triggered.emit()