class_name MatadorRagdoll
extends RefCounted
## Builds the matador's physical-bone ragdoll. Body joints are cone-twist with
## limited swing/twist (DP-tunable) so the corpse keeps its silhouette instead of
## folding into a flat "deflated" pile; the cape stays free (PIN) so it drapes.

# [bone, radius] → sphere collider; [bone, radius, height] → capsule.
const _BONES: Array = [
	["matador",       0.18],
	["COG",           0.12],
	["chest",         0.13, 0.30],
	["head",          0.14],
	["collarbone_L",  0.06, 0.18],
	["collarbone_R",  0.06, 0.18],
	["arm_L",         0.07, 0.22],
	["arm_R",         0.07, 0.22],
	["forearm_L",     0.06, 0.22],
	["forearm_R",     0.06, 0.22],
	["hand_L",        0.05, 0.12],
	["hand_R",        0.05, 0.12],
	["leg_L",         0.10, 0.32],
	["leg_R",         0.10, 0.32],
	["shin_L",        0.08, 0.28],
	["shin_R",        0.08, 0.28],
	["foot_L",        0.07, 0.18],
	["foot_R",        0.07, 0.18],
	["Bone",          0.04, 0.30],
	["Bone.001",      0.04, 0.34],
	["Bone.002",      0.04, 0.30],
]


# Reuse an existing simulator if the rig already has one, else build the bodies.
static func build(skeleton: Skeleton3D) -> PhysicalBoneSimulator3D:
	for child: Node in skeleton.get_children():
		if child is PhysicalBoneSimulator3D:
			(child as PhysicalBoneSimulator3D).active = false
			return child as PhysicalBoneSimulator3D

	var sim := PhysicalBoneSimulator3D.new()
	sim.active = false
	skeleton.add_child(sim)

	var swing := DP.f("mat_joint_swing")
	var twist := DP.f("mat_joint_twist")
	var damp := DP.f("mat_ragdoll_damp")

	for entry: Array in _BONES:
		var bname: String = entry[0]
		if skeleton.find_bone(bname) == -1:
			continue
		var pb := PhysicalBone3D.new()
		pb.bone_name       = bname
		pb.mass            = 0.4
		pb.linear_damp     = 0.1
		pb.collision_layer = 1
		pb.collision_mask  = 1
		if bname.begins_with("Bone"):
			# Cape: floppy cloth — free swing, light, draggy, one-way collision.
			pb.joint_type      = PhysicalBone3D.JOINT_TYPE_PIN
			pb.mass            = 0.15
			pb.linear_damp     = 0.5
			pb.angular_damp    = 0.7
			pb.collision_layer = 0
		else:
			# Body: cone-twist joints cap how far each bone bends from its rest
			# pose, so the silhouette holds; extra angular damp settles the flail.
			pb.joint_type   = PhysicalBone3D.JOINT_TYPE_CONE
			pb.angular_damp = damp
			pb.set(&"joint_constraints/swing_span", swing)
			pb.set(&"joint_constraints/twist_span", twist)
		var cs := CollisionShape3D.new()
		if entry.size() >= 3:
			var cap := CapsuleShape3D.new()
			cap.radius = entry[1]
			cap.height = entry[2]
			cs.shape = cap
		else:
			var sph := SphereShape3D.new()
			sph.radius = entry[1]
			cs.shape = sph
		pb.add_child(cs)
		sim.add_child(pb)

	return sim
