From 3d1e5dda3806807c60f2dabd96ea6d86915b3feb Mon Sep 17 00:00:00 2001 From: Rob Kelly Date: Sat, 28 Jun 2025 17:43:19 -0600 Subject: [PATCH] Stickers can be removed with spray tools --- src/equipment/point_spray/point_spray.gd | 4 ++-- src/equipment/sprayable.gd | 12 ++++++++++ src/equipment/sprayable.gd.uid | 1 + src/equipment/sticker_pack/sticker_pack.gd | 17 ++++++-------- src/equipment/sticker_pack/sticker_pack.tscn | 1 - src/equipment/sticker_pack/world_sticker.gd | 22 +++++++++++++++++++ .../sticker_pack/world_sticker.gd.uid | 1 + src/equipment/sticker_pack/world_sticker.tscn | 21 +++++++++++++++--- src/equipment/wide_spray/wide_spray.gd | 4 ++-- src/world/gunk_node/gunk_node.gd | 4 ++-- src/world/world_manager.tres | 2 +- 11 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 src/equipment/sprayable.gd create mode 100644 src/equipment/sprayable.gd.uid create mode 100644 src/equipment/sticker_pack/world_sticker.gd create mode 100644 src/equipment/sticker_pack/world_sticker.gd.uid diff --git a/src/equipment/point_spray/point_spray.gd b/src/equipment/point_spray/point_spray.gd index 3d55fa3..4993513 100644 --- a/src/equipment/point_spray/point_spray.gd +++ b/src/equipment/point_spray/point_spray.gd @@ -20,5 +20,5 @@ func _spray() -> void: (collider as GunkBody).paint_continuous( point, laser.get_collision_normal(), point_scale ) - if collider is GunkNode: - (collider as GunkNode).hit(damage) + if collider is Sprayable: + (collider as Sprayable).hit(damage) diff --git a/src/equipment/sprayable.gd b/src/equipment/sprayable.gd new file mode 100644 index 0000000..e45af83 --- /dev/null +++ b/src/equipment/sprayable.gd @@ -0,0 +1,12 @@ +class_name Sprayable extends StaticBody3D + + +## Called each frame this node takes a hit. +## +## Derived types should override `_hit()` as a lifecycle method. +func hit(damage: float) -> void: + _hit() + + +func _hit() -> void: + pass # Implemented in derived type diff --git a/src/equipment/sprayable.gd.uid b/src/equipment/sprayable.gd.uid new file mode 100644 index 0000000..df5a3cb --- /dev/null +++ b/src/equipment/sprayable.gd.uid @@ -0,0 +1 @@ +uid://ddpgqjf71eqm5 diff --git a/src/equipment/sticker_pack/sticker_pack.gd b/src/equipment/sticker_pack/sticker_pack.gd index 0f31850..d583596 100644 --- a/src/equipment/sticker_pack/sticker_pack.gd +++ b/src/equipment/sticker_pack/sticker_pack.gd @@ -47,21 +47,18 @@ func fire() -> void: func place_sticker() -> void: - var instance: Decal = sticker_scene.instantiate() + var instance: WorldSticker = sticker_scene.instantiate() var target: Node = raycast.get_collider() as Node if not target: push_warning("Tried to apply decal to non-node target ", raycast.get_collider()) return target.add_sibling(instance) - - instance.texture_albedo = get_selected_sticker() - instance.global_position = raycast.get_collision_point() - - # Build basis - var up := raycast.get_collision_normal() - var right := up.cross(global_basis.y).normalized() - var forward := -right.cross(up).normalized() - instance.global_basis = Basis(right, up, forward) + instance.place( + get_selected_sticker(), + raycast.get_collision_point(), + raycast.get_collision_normal(), + global_basis.y + ) print_debug("Sticker placed") diff --git a/src/equipment/sticker_pack/sticker_pack.tscn b/src/equipment/sticker_pack/sticker_pack.tscn index 30d13f9..f9e3e1f 100644 --- a/src/equipment/sticker_pack/sticker_pack.tscn +++ b/src/equipment/sticker_pack/sticker_pack.tscn @@ -18,7 +18,6 @@ sticker_scene = ExtResource("2_yigow") unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, 0.997564, -0.0697565, 0, 0.0697565, 0.997564, 0, 0, -0.15) target_position = Vector3(0, 0, -1) -collision_mask = 4 hit_from_inside = true [node name="RestingPosition" type="Marker3D" parent="."] diff --git a/src/equipment/sticker_pack/world_sticker.gd b/src/equipment/sticker_pack/world_sticker.gd new file mode 100644 index 0000000..7480525 --- /dev/null +++ b/src/equipment/sticker_pack/world_sticker.gd @@ -0,0 +1,22 @@ +class_name WorldSticker extends Sprayable + +@onready var decal: Decal = %Decal + + +func _hit() -> void: + # Remove on hit + queue_free() + + +## Place this sticker at a given point, aligned to the given normal, with the given texture. +func place(texture: Texture2D, point: Vector3, normal: Vector3, src_up: Vector3) -> void: + decal.texture_albedo = texture + global_position = point + + # Build basis + var up := normal + var right := up.cross(src_up).normalized() + var forward := -right.cross(up).normalized() + global_basis = Basis(right, up, forward) + +# TODO handle serialization & deserialization diff --git a/src/equipment/sticker_pack/world_sticker.gd.uid b/src/equipment/sticker_pack/world_sticker.gd.uid new file mode 100644 index 0000000..9862116 --- /dev/null +++ b/src/equipment/sticker_pack/world_sticker.gd.uid @@ -0,0 +1 @@ +uid://giosvggx808p diff --git a/src/equipment/sticker_pack/world_sticker.tscn b/src/equipment/sticker_pack/world_sticker.tscn index 7ec9a86..62cd508 100644 --- a/src/equipment/sticker_pack/world_sticker.tscn +++ b/src/equipment/sticker_pack/world_sticker.tscn @@ -1,6 +1,10 @@ -[gd_scene load_steps=4 format=3 uid="uid://dqc1a8xaqac8h"] +[gd_scene load_steps=6 format=3 uid="uid://dqc1a8xaqac8h"] [ext_resource type="Texture2D" uid="uid://cl8ui8nnoaa1i" path="res://assets/stickers/heart_suit_3d.png" id="1_e4i3l"] +[ext_resource type="Script" uid="uid://giosvggx808p" path="res://src/equipment/sticker_pack/world_sticker.gd" id="1_q766c"] + +[sub_resource type="SphereShape3D" id="SphereShape3D_e4i3l"] +radius = 0.09 [sub_resource type="PlaneMesh" id="PlaneMesh_e4i3l"] @@ -9,18 +13,29 @@ top_radius = 0.01 bottom_radius = 0.01 height = 0.2 -[node name="WorldSticker" type="Decal"] +[node name="WorldSticker" type="StaticBody3D"] +collision_layer = 4 +collision_mask = 0 +script = ExtResource("1_q766c") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("SphereShape3D_e4i3l") + +[node name="Decal" type="Decal" parent="."] +unique_name_in_owner = true size = Vector3(0.25, 0.1, 0.25) texture_albedo = ExtResource("1_e4i3l") upper_fade = 0.01 lower_fade = 0.01 [node name="DebugPlane" type="MeshInstance3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 0.848002, -0.529993, 0, 0.529993, 0.848002, 0, 0, 0) +transform = Transform3D(1, 0, 0, 0, 0.729219, -0.68428, 0, 0.68428, 0.729219, 0, 0, 0) visible = false mesh = SubResource("PlaneMesh_e4i3l") +skeleton = NodePath("../Decal") [node name="DebugNormal" type="MeshInstance3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.15, 0) visible = false mesh = SubResource("CylinderMesh_e4i3l") +skeleton = NodePath("../Decal") diff --git a/src/equipment/wide_spray/wide_spray.gd b/src/equipment/wide_spray/wide_spray.gd index 210c10c..901ff8f 100644 --- a/src/equipment/wide_spray/wide_spray.gd +++ b/src/equipment/wide_spray/wide_spray.gd @@ -61,8 +61,8 @@ func _spray() -> void: prev_target = target prev_point = point prev_normal = normal - elif collider is GunkNode: - (collider as GunkNode).hit(damage) + elif collider is Sprayable: + (collider as Sprayable).hit(damage) func _on_animation_finished(anim_name: StringName) -> void: diff --git a/src/world/gunk_node/gunk_node.gd b/src/world/gunk_node/gunk_node.gd index 64ee6e5..dbc412b 100644 --- a/src/world/gunk_node/gunk_node.gd +++ b/src/world/gunk_node/gunk_node.gd @@ -1,4 +1,4 @@ -class_name GunkNode extends StaticBody3D +class_name GunkNode extends Sprayable ## A static body which can be destroyed and collected by the player. ## Emitted immediately after this node has been destroyed by the player, @@ -30,7 +30,7 @@ func _enter_tree() -> void: func hit(damage: float = 0.05) -> void: _sustained_damage += damage _hit_this_frame = true - _hit() + super.hit(damage) ## Return this node's current damage as a proportion of it's total durability. diff --git a/src/world/world_manager.tres b/src/world/world_manager.tres index cc6c094..9feb715 100644 --- a/src/world/world_manager.tres +++ b/src/world/world_manager.tres @@ -301,7 +301,7 @@ vault_milestones = Dictionary[int, ExtResource("2_c37ff")]({ }) mp3_player_unlocked = false toothbrush_unlocked = false -stickers_unlocked = true +stickers_unlocked = false mp3_collection = Array[ExtResource("3_yiuq5")]([]) grunk_tank = 0.0 grunk_vault = 0.0