extends Node3D var pickup_type: String = "health" var heal_amount: int = 20 var collected: bool = false var bob_t: float = 0.0 @onready var mesh_node: MeshInstance3D = $PickupMesh var mat: StandardMaterial3D const PICKUP_RADIUS := 1.0 const COLORS := { "health": Color(0.1, 0.9, 0.25), "score": Color(1.0, 0.85, 0.1), } func setup(p_type: String, p_heal: int = 20) -> void: pickup_type = p_type heal_amount = p_heal func _ready() -> void: add_to_group("pickups") bob_t = randf() * TAU mat = mesh_node.material_override.duplicate() as StandardMaterial3D mesh_node.material_override = mat var col: Color = COLORS.get(pickup_type, Color.WHITE) mat.albedo_color = col mat.emission_enabled = true mat.emission = col mat.emission_energy_multiplier = 0.6 scale = Vector3.ZERO var tw := create_tween() tw.tween_property(self, "scale", Vector3.ONE, 0.22).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) func _process(delta: float) -> void: if collected: return bob_t += delta mesh_node.position.y = 0.3 + sin(bob_t * 2.6) * 0.1 mesh_node.rotation.y += delta * 2.2 for p in get_tree().get_nodes_in_group("player"): if not is_instance_valid(p): continue if (p as Node3D).global_position.distance_to(global_position) < PICKUP_RADIUS: _collect(p) return func _collect(player: Node3D) -> void: collected = true match pickup_type: "health": player.call("heal", heal_amount) "score": for m in get_tree().get_nodes_in_group("main"): if is_instance_valid(m): m.call("add_bonus_score", 30) break var tw := create_tween() tw.tween_property(self, "scale", Vector3(1.6, 1.6, 1.6), 0.07) tw.tween_property(self, "scale", Vector3.ZERO, 0.1) tw.tween_callback(queue_free)