44 lines
1.9 KiB
GDScript
44 lines
1.9 KiB
GDScript
# Target-following effects use actor-local offset. Snapshot effects use the
|
|
# fly-target's world position and a world-aligned offset (40250 type 10).
|
|
extends Node
|
|
const CONVERSION := Basis(Vector3(0.01, 0, 0), Vector3(0, 0, -0.01), Vector3(0, 0.01, 0))
|
|
var target: WeakRef
|
|
var offset := Vector3.ZERO
|
|
func configure(node: Node3D, source_offset: Vector3, following: bool) -> bool:
|
|
if not is_instance_valid(node) or not node.is_inside_tree(): return false
|
|
target = weakref(node)
|
|
offset = CONVERSION * source_offset
|
|
process_priority = 100
|
|
set_process(following)
|
|
if following:
|
|
_process(0.0)
|
|
else:
|
|
get_parent().global_position = fly_target_position(node) + offset
|
|
return true
|
|
static func fly_target_position(node: Node3D) -> Vector3:
|
|
# The reference model-index 0 sphere is built from bone OBBs, not the
|
|
# union of visible attachments or the rendered vertex AABB.
|
|
var models := node.find_children("*", "Metin2Model", true, false)
|
|
if node.has_method("get_fly_target_bounds"): models.push_front(node)
|
|
for model in models:
|
|
var result: Dictionary = model.get_fly_target_bounds()
|
|
if result.get("valid", false):
|
|
var body_bounds: AABB = result.bounds
|
|
return model.to_global(body_bounds.get_center())
|
|
# The reference returns the model bounding sphere centre, not its feet.
|
|
var meshes := node.find_children("*", "MeshInstance3D", true, false)
|
|
var bounds := AABB()
|
|
var found := false
|
|
for mesh in meshes:
|
|
if mesh.mesh == null or not mesh.is_visible_in_tree(): continue
|
|
var box: AABB = mesh.global_transform * mesh.get_aabb()
|
|
bounds = bounds.merge(box) if found else box
|
|
found = true
|
|
return bounds.get_center() if found else node.global_position
|
|
func _process(_delta: float) -> void:
|
|
var node: Node3D = target.get_ref() if target else null
|
|
if not is_instance_valid(node) or not node.is_inside_tree():
|
|
get_parent().queue_free()
|
|
return
|
|
get_parent().global_transform = node.global_transform * Transform3D(Basis.IDENTITY, offset)
|