Ability refinement, more and more matadors spawn after clears

This commit is contained in:
2026-06-10 21:53:57 +03:00
parent c1852e8736
commit 09c39e068b
22 changed files with 386 additions and 27 deletions
+97 -7
View File
@@ -21,11 +21,18 @@ const TAIL_BONES: Array = [
&"tail_5", &"tail_6",
&"tail_tip_1", &"tail_tip_2", &"tail_tip_2_end",
]
var _tail_idx: Array[int] = []
var _tail_world: Array[Vector3] = []
var _tail_prev: Array[Vector3] = []
var _tail_lengths: Array[float] = []
var _tail_rest_dir: Array[Vector3] = []
var _tail_idx: Array[int] = []
var _tail_world: Array[Vector3] = []
var _tail_prev: Array[Vector3] = []
var _tail_lengths: Array[float] = []
var _tail_rest_dir: Array[Vector3] = []
var _tail_parent_idx: int = -1
var tail_ragdoll: bool = false
var _prev_on_floor: bool = true
var _dbg_on: bool = false
var _dbg_nodes: Array[MeshInstance3D] = []
func setup(player: CharacterBody3D, bull: Node3D) -> void:
@@ -84,6 +91,14 @@ func _setup_tail() -> void:
_tail_rest_dir.append(seg_skel.normalized() if seg_skel.length() > 0.001 else Vector3(0, 0, 1))
_tail_rest_dir.append(_tail_rest_dir[-1])
_tail_parent_idx = _skeleton.get_bone_parent(_tail_idx[0])
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventKey and event.pressed and not event.echo:
if event.physical_keycode == KEY_QUOTELEFT:
_dbg_toggle()
func _process(delta: float) -> void:
if not _skeleton:
@@ -91,6 +106,8 @@ func _process(delta: float) -> void:
_wobble_body(delta)
_update_tail(delta)
_apply_tail()
if _dbg_on:
_dbg_update()
# ── Body Wobble ───────────────────────────────────────────────────────────────
@@ -128,10 +145,31 @@ func _update_tail(delta: float) -> void:
var gravity := Vector3(0.0, -DP.f("tail_gravity"), 0.0)
var damping := 1.0 - clampf(DP.f("tail_damping"), 0.0, 0.99)
var anchor: Vector3 = _skeleton.to_global(_skeleton.get_bone_global_rest(_tail_idx[0]).origin)
var anchor: Vector3
if _tail_parent_idx >= 0:
var parent_t := _skeleton.get_bone_global_pose(_tail_parent_idx)
anchor = _skeleton.to_global((parent_t * _skeleton.get_bone_rest(_tail_idx[0])).origin)
else:
anchor = _skeleton.to_global(_skeleton.get_bone_global_rest(_tail_idx[0]).origin)
_tail_world[0] = anchor
_tail_prev[0] = anchor
var on_floor := _player.is_on_floor()
if not on_floor and _prev_on_floor:
# Bull just left the ground — push all tail particles upward with it
for i: int in range(1, _tail_world.size()):
_tail_prev[i] = _tail_world[i] - _player.velocity * delta
_prev_on_floor = on_floor
var gravity_mult: float
if tail_ragdoll:
gravity_mult = 2.5
elif not on_floor:
gravity_mult = 0.15
else:
gravity_mult = 1.0
gravity *= gravity_mult
var flat_speed: float = Vector2(_player.velocity.x, _player.velocity.z).length()
var wag_strength: float = lerpf(DP.f("tail_wag_idle"), 0.0, clampf(flat_speed / 3.0, 0.0, 1.0))
var wag_freq: float = DP.f("tail_wag_freq")
@@ -141,7 +179,8 @@ func _update_tail(delta: float) -> void:
for i in range(1, _tail_world.size()):
var vel: Vector3 = (_tail_world[i] - _tail_prev[i]) * damping
_tail_prev[i] = _tail_world[i]
var wag := basis_x * sin(time * wag_freq + i * 0.5) * wag_strength
var wag := Vector3.ZERO if tail_ragdoll \
else basis_x * sin(time * wag_freq + i * 0.5) * wag_strength
_tail_world[i] = _tail_world[i] + vel + gravity * (delta * delta) + wag * delta
for i in range(1, _tail_world.size()):
@@ -195,6 +234,57 @@ func _apply_tail() -> void:
_skeleton.set_bone_global_pose_override(idx, Transform3D(new_basis, pos_skel), 1.0, false)
# ── Debug Visualization ───────────────────────────────────────────────────────
func _dbg_toggle() -> void:
if _dbg_on:
for n: MeshInstance3D in _dbg_nodes:
if is_instance_valid(n):
n.queue_free()
_dbg_nodes.clear()
_dbg_on = false
print("TailDebug OFF")
else:
_dbg_build()
_dbg_on = true
var pname := _skeleton.get_bone_name(_tail_parent_idx) if _tail_parent_idx >= 0 else "none"
print("TailDebug ON parent_bone=", pname, " bull_pos=", _bull.global_position)
func _dbg_build() -> void:
var root: Node = _player.get_parent()
var n: int = _tail_world.size()
for i: int in n:
var mat := StandardMaterial3D.new()
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
mat.render_priority = 1
mat.albedo_color = Color.RED if i == 0 \
else Color(1.0 - float(i) / n, 0.4 + 0.6 * float(i) / n, 0.0)
var sm := SphereMesh.new()
sm.radius = 0.10 if i == 0 else 0.06
sm.height = sm.radius * 2.0
sm.radial_segments = 6
sm.rings = 3
sm.material = mat
var mi := MeshInstance3D.new()
mi.mesh = sm
root.add_child(mi)
_dbg_nodes.append(mi)
func _dbg_update() -> void:
for i: int in _dbg_nodes.size():
_dbg_nodes[i].global_position = _tail_world[i]
# Print positions every ~60 frames
if Engine.get_process_frames() % 60 == 0:
var parent_y := 0.0
if _tail_parent_idx >= 0:
parent_y = _skeleton.to_global(_skeleton.get_bone_global_pose(_tail_parent_idx).origin).y
print("anchor_Y=%.2f parent_bone_Y=%.2f player_Y=%.2f on_floor=%s" % [
_tail_world[0].y, parent_y, _player.global_position.y,
str(_player.is_on_floor())])
# ── Utility ───────────────────────────────────────────────────────────────────
func _find_skeleton(node: Node) -> Skeleton3D: