class_name FX # Small burst of colored spheres flying outward from impact point. static func hit_spark(pos: Vector3, parent: Node, color: Color = Color(1.0, 0.72, 0.1)) -> void: const COUNT := 8 for i in range(COUNT): var m := MeshInstance3D.new() var sphere := SphereMesh.new() sphere.radius = 0.12 sphere.height = 0.24 sphere.radial_segments = 4 sphere.rings = 2 var mat := StandardMaterial3D.new() mat.albedo_color = color mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA m.material_override = mat m.mesh = sphere parent.add_child(m) m.global_position = pos var angle := TAU * float(i) / float(COUNT) + randf() * 0.6 var dist := randf_range(0.7, 1.8) var end := pos + Vector3(cos(angle) * dist, randf_range(0.3, 1.3), sin(angle) * dist) var tw := m.create_tween().set_parallel(true) tw.tween_property(m, "global_position", end, 0.28) tw.tween_property(m, "scale", Vector3(0.05, 0.05, 0.05), 0.28) tw.tween_method(func(a: float): mat.albedo_color.a = a, 1.0, 0.0, 0.28) tw.chain().tween_callback(m.queue_free) # Expanding smoke sphere for merges. static func merge_smoke(pos: Vector3, parent: Node) -> void: var m := MeshInstance3D.new() var sphere := SphereMesh.new() sphere.radius = 0.4 sphere.height = 0.8 var mat := StandardMaterial3D.new() mat.albedo_color = Color(0.90, 0.90, 0.90, 0.85) mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA mat.cull_mode = BaseMaterial3D.CULL_DISABLED m.material_override = mat m.mesh = sphere parent.add_child(m) m.global_position = pos var tw := m.create_tween().set_parallel(true) tw.tween_property(m, "scale", Vector3(5.5, 3.5, 5.5), 0.55) tw.tween_method(func(a: float): mat.albedo_color.a = a, 0.85, 0.0, 0.55) tw.chain().tween_callback(m.queue_free)