Add interactive mushroom pickup and highlight mechanics with pop sound
Some checks failed
Deploy Promiscuity Auth API / deploy (push) Successful in 1m1s
Deploy Promiscuity Character API / deploy (push) Has been cancelled
Deploy Promiscuity Crafting API / deploy (push) Has been cancelled
Deploy Promiscuity Inventory API / deploy (push) Has been cancelled
Deploy Promiscuity Locations API / deploy (push) Has been cancelled
Deploy Promiscuity Mail API / deploy (push) Has been cancelled
Deploy Promiscuity World API / deploy (push) Has been cancelled
k8s smoke test / test (push) Has been cancelled

This commit is contained in:
null 2026-05-28 18:34:35 -05:00
parent e6a442c98b
commit 09e6b4cc90

View File

@ -6,11 +6,20 @@ extends Node3D
@export var max_mushrooms_in_radius := 3
@export var check_radius := 1.5
@export var max_total_mushrooms := 50
@export var interact_radius := 2.0
@export var look_at_threshold := 0.95
static var total_mushrooms := 0
@onready var spread_timer: Timer = $SpreadTimer
@onready var ground_ray: RayCast3D = $GroundRay
@onready var cap: MeshInstance3D = $Cap
@onready var stem: MeshInstance3D = $Stem
var _player_in_range := false
var _is_highlighted := false
var highlight_mat: StandardMaterial3D
var _audio_player: AudioStreamPlayer3D
func _ready() -> void:
total_mushrooms += 1
@ -19,6 +28,111 @@ func _ready() -> void:
# Randomize initial scale for variety
scale = Vector3.ONE * randf_range(0.8, 1.2)
rotation.y = randf_range(0, TAU)
# Setup interaction area
var area = Area3D.new()
add_child(area)
var shape = CollisionShape3D.new()
var sphere = SphereShape3D.new()
sphere.radius = interact_radius
shape.shape = sphere
area.add_child(shape)
area.body_entered.connect(_on_body_entered)
area.body_exited.connect(_on_body_exited)
highlight_mat = StandardMaterial3D.new()
highlight_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
highlight_mat.albedo_color = Color(1.0, 1.0, 1.0, 0.3)
highlight_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
_audio_player = AudioStreamPlayer3D.new()
_audio_player.stream = preload("res://assets/audio/pop.ogg")
add_child(_audio_player)
func _process(_delta: float) -> void:
if not _player_in_range:
_set_highlight(false)
return
var cam = get_viewport().get_camera_3d()
if not cam:
_set_highlight(false)
return
var dir_to_mushroom = (global_position - cam.global_position).normalized()
var forward = -cam.global_transform.basis.z
var my_dot = forward.dot(dir_to_mushroom)
if my_dot > look_at_threshold:
# Check if we are the most directly looked-at mushroom in range
var is_best = true
for mushroom in get_tree().get_nodes_in_group("mushrooms"):
if mushroom == self or not mushroom.get("_player_in_range"):
continue
var m_dir = (mushroom.global_position - cam.global_position).normalized()
var m_dot = forward.dot(m_dir)
if m_dot > my_dot:
is_best = false
break
elif m_dot == my_dot and mushroom.get_instance_id() > get_instance_id():
# Tie breaker
is_best = false
break
_set_highlight(is_best)
else:
_set_highlight(false)
func _set_highlight(value: bool) -> void:
if _is_highlighted == value: return
_is_highlighted = value
if value:
if cap: cap.material_overlay = highlight_mat
if stem: stem.material_overlay = highlight_mat
else:
if cap: cap.material_overlay = null
if stem: stem.material_overlay = null
func _on_body_entered(body: Node3D) -> void:
if body.is_in_group("player"):
_player_in_range = true
func _on_body_exited(body: Node3D) -> void:
if body.is_in_group("player"):
_player_in_range = false
_set_highlight(false)
func _unhandled_input(event: InputEvent) -> void:
if _is_highlighted and event.is_action_pressed("interact"):
get_viewport().set_input_as_handled()
_collect_mushroom()
func _collect_mushroom() -> void:
# Disable interaction and visuals
_is_highlighted = false
_set_highlight(false)
_player_in_range = false
if cap: cap.visible = false
if stem: stem.visible = false
# Stop spreading logic
spread_timer.stop()
# Disable processing so it can't be interacted with again
set_process_unhandled_input(false)
set_process(false)
# Play sound
_audio_player.play()
# Wait for sound to finish, then free
await _audio_player.finished
queue_free()
func _setup_timer() -> void:
spread_timer.wait_time = randf_range(spread_interval_min, spread_interval_max)