From 09c39e068bd2ceb288a4ff7b13b57af178810562 Mon Sep 17 00:00:00 2001 From: Richard Aasa Date: Wed, 10 Jun 2026 21:53:57 +0300 Subject: [PATCH] Ability refinement, more and more matadors spawn after clears --- .gitignore | 3 - Animations/anim_publik_mees.gd.uid | 1 + Animations/mees_plaksutab.gd.uid | 1 + Assets/matador.gd.uid | 1 + animation_player.gd.uid | 1 + bull_legs.gd | 104 +++++++++++- camera_iso.gd.uid | 1 + debug_params.gd | 2 +- hud.gd.uid | 1 + matador.gd | 7 +- matador.gd.uid | 1 + matador_2.gd.uid | 1 + matador_spawn.gd | 31 +++- matador_spawn.gd.uid | 1 + player.gd | 243 ++++++++++++++++++++++++++++- ps1_filter.gdshader.uid | 1 + publikum_controller.gd.uid | 1 + scene.tscn | 8 +- tests/gameplay_test.gd.uid | 1 + tests/logic_test.gd.uid | 1 + tests/ragdoll_throw_test.gd.uid | 1 + tests/screenshot_test.gd.uid | 1 + 22 files changed, 386 insertions(+), 27 deletions(-) create mode 100644 Animations/anim_publik_mees.gd.uid create mode 100644 Animations/mees_plaksutab.gd.uid create mode 100644 Assets/matador.gd.uid create mode 100644 animation_player.gd.uid create mode 100644 camera_iso.gd.uid create mode 100644 hud.gd.uid create mode 100644 matador.gd.uid create mode 100644 matador_2.gd.uid create mode 100644 matador_spawn.gd.uid create mode 100644 ps1_filter.gdshader.uid create mode 100644 publikum_controller.gd.uid create mode 100644 tests/gameplay_test.gd.uid create mode 100644 tests/logic_test.gd.uid create mode 100644 tests/ragdoll_throw_test.gd.uid create mode 100644 tests/screenshot_test.gd.uid diff --git a/.gitignore b/.gitignore index a93c939..c506783 100644 --- a/.gitignore +++ b/.gitignore @@ -2,9 +2,6 @@ .godot/ /android/ -# Godot UID sidecar files (auto-generated, machine-local) -*.uid - # JetBrains IDE — contains absolute paths (Godot binary, SDK dirs), varies per user .idea/ diff --git a/Animations/anim_publik_mees.gd.uid b/Animations/anim_publik_mees.gd.uid new file mode 100644 index 0000000..6a16b75 --- /dev/null +++ b/Animations/anim_publik_mees.gd.uid @@ -0,0 +1 @@ +uid://wj6tgh8nb0ka diff --git a/Animations/mees_plaksutab.gd.uid b/Animations/mees_plaksutab.gd.uid new file mode 100644 index 0000000..1660906 --- /dev/null +++ b/Animations/mees_plaksutab.gd.uid @@ -0,0 +1 @@ +uid://gt3kfchac3m3 diff --git a/Assets/matador.gd.uid b/Assets/matador.gd.uid new file mode 100644 index 0000000..0cb4e05 --- /dev/null +++ b/Assets/matador.gd.uid @@ -0,0 +1 @@ +uid://bn3xwnlktwdlf diff --git a/animation_player.gd.uid b/animation_player.gd.uid new file mode 100644 index 0000000..a66d352 --- /dev/null +++ b/animation_player.gd.uid @@ -0,0 +1 @@ +uid://b6gdjsr6fcwc2 diff --git a/bull_legs.gd b/bull_legs.gd index 0941fef..df25d0c 100644 --- a/bull_legs.gd +++ b/bull_legs.gd @@ -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: diff --git a/camera_iso.gd.uid b/camera_iso.gd.uid new file mode 100644 index 0000000..e538a0d --- /dev/null +++ b/camera_iso.gd.uid @@ -0,0 +1 @@ +uid://cpyq2r5cq653g diff --git a/debug_params.gd b/debug_params.gd index 1015c50..b2ec21b 100644 --- a/debug_params.gd +++ b/debug_params.gd @@ -116,7 +116,7 @@ func _register_all() -> void: _reg_f("Matador", "mat_roll_duration", 0.45, 0.1, 1.5, 0.05) # ── Abilities ───────────────────────────────────────────────────────────── _reg_f("Abilities", "kick_cooldown", 1.5, 0.2, 10.0, 0.1) - _reg_f("Abilities", "kick_range", 2.5, 0.5, 8.0, 0.1) + _reg_f("Abilities", "kick_range", 3.5, 0.5, 8.0, 0.1) _reg_f("Abilities", "kick_strength", 12.0, 1.0, 30.0) _reg_f("Abilities", "slam_cooldown", 4.0, 0.5, 15.0, 0.1) _reg_f("Abilities", "slam_range", 4.0, 1.0, 10.0, 0.1) diff --git a/hud.gd.uid b/hud.gd.uid new file mode 100644 index 0000000..b449308 --- /dev/null +++ b/hud.gd.uid @@ -0,0 +1 @@ +uid://butd6b3tdwxrv diff --git a/matador.gd b/matador.gd index 14333fb..cdd5ee0 100644 --- a/matador.gd +++ b/matador.gd @@ -367,9 +367,10 @@ func _enter_ragdoll(hit_dir: Vector3, bull_speed: float) -> void: _death_player.pitch_scale = randf_range(0.9, 1.1) _death_player.play() - var cam := _bull.get_node_or_null("Camera3D") - if cam: - cam.call(&"trigger_hit", clampf(bull_speed / 15.0, 0.4, 1.0)) + if _bull != null: + var cam := _bull.get_node_or_null("Camera3D") + if cam: + cam.call(&"trigger_hit", clampf(bull_speed / 15.0, 0.4, 1.0)) velocity = Vector3.ZERO collision_layer = 0 diff --git a/matador.gd.uid b/matador.gd.uid new file mode 100644 index 0000000..5f46381 --- /dev/null +++ b/matador.gd.uid @@ -0,0 +1 @@ +uid://bvfa7xi0luysk diff --git a/matador_2.gd.uid b/matador_2.gd.uid new file mode 100644 index 0000000..2d32f7d --- /dev/null +++ b/matador_2.gd.uid @@ -0,0 +1 @@ +uid://cph15mof257wb diff --git a/matador_spawn.gd b/matador_spawn.gd index c8504dd..5304954 100644 --- a/matador_spawn.gd +++ b/matador_spawn.gd @@ -6,10 +6,13 @@ const MATADOR := preload("res://Matador.tscn") const RESPAWN_COOLDOWN := 8.0 var _respawn_cooldown: float = 0.0 +var _wave_count: int = 1 +var _alive: int = 0 func _ready() -> void: add_to_group(&"matador_spawn") + _wave_count = maxi(1, int(DP.f("mat_spawn_count"))) _spawn.call_deferred() @@ -25,25 +28,43 @@ func _unhandled_input(event: InputEvent) -> void: func _spawn() -> void: - var count: int = int(DP.f("mat_spawn_count")) + var positions := _spread_positions(_wave_count) + for pos: Vector3 in positions: + _spawn_at(pos) + + +func _spread_positions(count: int) -> Array[Vector3]: + var positions: Array[Vector3] = [] + var arena_r := DP.f("mat_wander_radius") * 0.72 + var min_r := 5.0 for i: int in count: - _spawn_one() + var sector := TAU / count + var angle := sector * i + randf_range(-sector * 0.35, sector * 0.35) + var radius := randf_range(min_r, arena_r) + positions.append(Vector3(cos(angle) * radius, 1.0, sin(angle) * radius)) + return positions -func _spawn_one() -> void: +func _spawn_at(pos: Vector3) -> void: var m: Node3D = MATADOR.instantiate() - m.position = Vector3(0.0, 1.0, 0.0) + m.position = pos get_parent().add_child(m) m.killed.connect(_on_matador_killed) + _alive += 1 func _on_matador_killed() -> void: matador_killed.emit() - _spawn_one.call_deferred() + _alive -= 1 + if _alive <= 0: + _wave_count *= 2 + _spawn.call_deferred() func reset_spawn() -> void: for m: Node in get_tree().get_nodes_in_group(&"matador"): m.queue_free() await get_tree().process_frame + _wave_count = maxi(1, int(DP.f("mat_spawn_count"))) + _alive = 0 _spawn() diff --git a/matador_spawn.gd.uid b/matador_spawn.gd.uid new file mode 100644 index 0000000..a944535 --- /dev/null +++ b/matador_spawn.gd.uid @@ -0,0 +1 @@ +uid://dou5ar6tkmng1 diff --git a/player.gd b/player.gd index e526281..4fa1ffc 100644 --- a/player.gd +++ b/player.gd @@ -21,6 +21,8 @@ var _thrust_left_charge: float = 0.0 var _thrust_right_charge: float = 0.0 var _charge_was_full: bool = false +var _slam_ring_mesh: ArrayMesh = null + # Ability system — kick=0, slam=1, dash=2 var ability_cd: Array[float] = [0.0, 0.0, 0.0] var _ability_active: bool = false @@ -248,7 +250,12 @@ func _activate_kick() -> void: if _bull_anim and _bull_anim.has_animation(&"Armature|FOOTKICK"): _bull_anim.play(&"Armature|FOOTKICK") _ability_timer = _bull_anim.get_animation(&"Armature|FOOTKICK").length - _hit_matadors_cone(DP.f("kick_range"), deg_to_rad(60.0), DP.f("kick_strength")) + var raw := cube_guy.global_transform.basis.z + var back := -Vector3(raw.x, 0.0, raw.z).normalized() + _spawn_kick_fx(back) + get_tree().create_timer(0.2).timeout.connect( + func() -> void: _hit_matadors_cone(DP.f("kick_range"), deg_to_rad(85.0), DP.f("kick_strength"), back) + ) func _activate_slam() -> void: @@ -259,7 +266,12 @@ func _activate_slam() -> void: if _bull_anim and _bull_anim.has_animation(&"Armature|SLAM"): _bull_anim.play(&"Armature|SLAM") _ability_timer = _bull_anim.get_animation(&"Armature|SLAM").length - _hit_matadors_radius(DP.f("slam_range"), DP.f("slam_strength")) + _legs.set(&"tail_ragdoll", true) + _spawn_slam_fx() + # Delay hit slightly so it lands when the first ring reaches the targets + get_tree().create_timer(0.15).timeout.connect( + func() -> void: _hit_matadors_radius(DP.f("slam_range"), DP.f("slam_strength")) + ) func _activate_dash() -> void: @@ -280,9 +292,10 @@ func _activate_dash() -> void: _huff_player.play() -func _hit_matadors_cone(range_m: float, half_angle_rad: float, strength: float) -> void: +func _hit_matadors_cone(range_m: float, half_angle_rad: float, strength: float, + dir: Vector3 = Vector3.ZERO) -> void: var raw := cube_guy.global_transform.basis.z - var forward := Vector3(raw.x, 0.0, raw.z).normalized() + var forward := dir if dir.length_squared() > 0.01 else Vector3(raw.x, 0.0, raw.z).normalized() for mat: Node in get_tree().get_nodes_in_group(&"matador"): var to_mat: Vector3 = (mat as Node3D).global_position - global_position to_mat.y = 0.0 @@ -304,6 +317,227 @@ func _hit_matadors_radius(range_m: float, strength: float) -> void: mat.call(&"apply_ability_hit", (away + Vector3.UP * 0.6).normalized(), strength) +func _spawn_slam_fx() -> void: + if not _slam_ring_mesh: + _slam_ring_mesh = _make_slam_ring_mesh() + var max_r := DP.f("slam_range") + var origin := global_position + Vector3(0.0, -0.5, 0.0) + _launch_slam_ring(origin, max_r, 0.00, 0.55, Color(1.00, 0.70, 0.10, 0.85)) + _launch_slam_ring(origin, max_r, 0.10, 0.52, Color(1.00, 0.50, 0.10, 0.65)) + _launch_slam_ring(origin, max_r, 0.20, 0.48, Color(0.90, 0.30, 0.10, 0.50)) + _spawn_slam_dust(origin) + camera_pivot.call(&"trigger_hit", 0.60) + + +func _launch_slam_ring(origin: Vector3, max_r: float, + delay: float, duration: float, col: Color) -> void: + var mat := StandardMaterial3D.new() + mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA + mat.albedo_color = Color(col.r, col.g, col.b, 0.0) + mat.cull_mode = BaseMaterial3D.CULL_DISABLED + + var mi := MeshInstance3D.new() + mi.mesh = _slam_ring_mesh + mi.material_override = mat + mi.scale = Vector3(0.02, 1.0, 0.02) + get_parent().add_child(mi) + mi.global_position = origin + + var tween := create_tween() + tween.set_parallel(true) + tween.tween_property(mi, "scale", + Vector3(max_r, 1.0, max_r), duration)\ + .set_delay(delay)\ + .set_trans(Tween.TRANS_EXPO)\ + .set_ease(Tween.EASE_OUT) + var fade := func(a: float) -> void: mat.albedo_color.a = a + tween.tween_method(fade, col.a, 0.0, duration)\ + .set_delay(delay)\ + .set_trans(Tween.TRANS_SINE)\ + .set_ease(Tween.EASE_IN) + tween.tween_callback(mi.queue_free).set_delay(delay + duration + 0.05) + + +func _spawn_slam_dust(origin: Vector3) -> void: + var mat := StandardMaterial3D.new() + mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA + mat.vertex_color_use_as_albedo = true + mat.cull_mode = BaseMaterial3D.CULL_DISABLED + + var sphere := SphereMesh.new() + sphere.radius = 0.09 + sphere.height = 0.18 + sphere.radial_segments = 4 + sphere.rings = 2 + sphere.material = mat + + var ramp := Gradient.new() + ramp.set_color(0, Color(0.88, 0.74, 0.46, 1.0)) + ramp.set_color(1, Color(0.88, 0.74, 0.46, 0.0)) + + var scale_curve := Curve.new() + scale_curve.add_point(Vector2(0.0, 0.25)) + scale_curve.add_point(Vector2(0.35, 1.6)) + scale_curve.add_point(Vector2(1.00, 0.0)) + + var p := CPUParticles3D.new() + p.one_shot = true + p.explosiveness = 0.85 + p.amount = 48 + p.lifetime = 1.1 + p.randomness = 0.5 + p.local_coords = false + p.direction = Vector3.UP + p.spread = 85.0 + p.gravity = Vector3(0.0, -7.0, 0.0) + p.initial_velocity_min = 3.5 + p.initial_velocity_max = 10.0 + p.scale_amount_min = 0.5 + p.scale_amount_max = 2.0 + p.mesh = sphere + p.color_ramp = ramp + p.scale_amount_curve = scale_curve + get_parent().add_child(p) + p.global_position = origin + p.restart() + get_tree().create_timer(2.5).timeout.connect(func() -> void: + if is_instance_valid(p): p.queue_free() + ) + + +func _spawn_kick_fx(back_dir: Vector3) -> void: + var origin := global_position + back_dir * 0.55 + Vector3(0.0, -0.25, 0.0) + _spawn_kick_dust(origin, back_dir) + _spawn_kick_stones(origin, back_dir) + camera_pivot.call(&"trigger_hit", 0.35) + + +func _spawn_kick_dust(origin: Vector3, back_dir: Vector3) -> void: + var mat := StandardMaterial3D.new() + mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA + mat.vertex_color_use_as_albedo = true + mat.cull_mode = BaseMaterial3D.CULL_DISABLED + + var sphere := SphereMesh.new() + sphere.radius = 0.12 + sphere.height = 0.24 + sphere.radial_segments = 4 + sphere.rings = 2 + sphere.material = mat + + var ramp := Gradient.new() + ramp.set_color(0, Color(0.80, 0.68, 0.42, 0.9)) + ramp.set_color(1, Color(0.80, 0.68, 0.42, 0.0)) + + var scale_curve := Curve.new() + scale_curve.add_point(Vector2(0.0, 0.3)) + scale_curve.add_point(Vector2(0.3, 1.5)) + scale_curve.add_point(Vector2(1.0, 0.0)) + + var p := CPUParticles3D.new() + p.one_shot = true + p.explosiveness = 0.80 + p.amount = 40 + p.lifetime = 1.2 + p.randomness = 0.5 + p.local_coords = false + p.direction = (back_dir + Vector3(0.0, 0.7, 0.0)).normalized() + p.spread = 65.0 + p.gravity = Vector3(0.0, -6.0, 0.0) + p.initial_velocity_min = 3.0 + p.initial_velocity_max = 9.0 + p.scale_amount_min = 0.5 + p.scale_amount_max = 2.2 + p.mesh = sphere + p.color_ramp = ramp + p.scale_amount_curve = scale_curve + get_parent().add_child(p) + p.global_position = origin + p.restart() + get_tree().create_timer(2.5).timeout.connect(func() -> void: + if is_instance_valid(p): p.queue_free() + ) + + +func _spawn_kick_stones(origin: Vector3, back_dir: Vector3) -> void: + var mat := StandardMaterial3D.new() + mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA + mat.vertex_color_use_as_albedo = true + mat.cull_mode = BaseMaterial3D.CULL_DISABLED + + var sphere := SphereMesh.new() + sphere.radius = 0.055 + sphere.height = 0.11 + sphere.radial_segments = 3 + sphere.rings = 1 + sphere.material = mat + + var ramp := Gradient.new() + ramp.set_color(0, Color(0.62, 0.58, 0.52, 1.0)) + ramp.set_color(1, Color(0.62, 0.58, 0.52, 0.0)) + + var scale_curve := Curve.new() + scale_curve.add_point(Vector2(0.0, 1.0)) + scale_curve.add_point(Vector2(0.6, 1.0)) + scale_curve.add_point(Vector2(1.0, 0.0)) + + var p := CPUParticles3D.new() + p.one_shot = true + p.explosiveness = 0.92 + p.amount = 14 + p.lifetime = 0.65 + p.randomness = 0.6 + p.local_coords = false + p.direction = (back_dir + Vector3(0.0, 0.35, 0.0)).normalized() + p.spread = 45.0 + p.gravity = Vector3(0.0, -9.8, 0.0) + p.initial_velocity_min = 5.0 + p.initial_velocity_max = 14.0 + p.scale_amount_min = 0.5 + p.scale_amount_max = 1.8 + p.mesh = sphere + p.color_ramp = ramp + p.scale_amount_curve = scale_curve + get_parent().add_child(p) + p.global_position = origin + p.restart() + get_tree().create_timer(2.0).timeout.connect(func() -> void: + if is_instance_valid(p): p.queue_free() + ) + + +func _make_slam_ring_mesh() -> ArrayMesh: + const INNER_R: float = 0.82 + const OUTER_R: float = 1.00 + const SEGMENTS: int = 48 + + var verts := PackedVector3Array() + var indices := PackedInt32Array() + + for i: int in SEGMENTS: + var a0 := i / float(SEGMENTS) * TAU + var a1 := (i + 1) / float(SEGMENTS) * TAU + var vi := i * 4 + verts.append(Vector3(cos(a0) * INNER_R, 0.0, sin(a0) * INNER_R)) + verts.append(Vector3(cos(a0) * OUTER_R, 0.0, sin(a0) * OUTER_R)) + verts.append(Vector3(cos(a1) * OUTER_R, 0.0, sin(a1) * OUTER_R)) + verts.append(Vector3(cos(a1) * INNER_R, 0.0, sin(a1) * INNER_R)) + indices.append_array([vi, vi + 2, vi + 1, vi, vi + 3, vi + 2]) + + var arrays: Array = [] + arrays.resize(Mesh.ARRAY_MAX) + arrays[Mesh.ARRAY_VERTEX] = verts + arrays[Mesh.ARRAY_INDEX] = indices + + var mesh := ArrayMesh.new() + mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays) + return mesh + + func _apply_thrust(dir: Vector3) -> void: var impulse := DP.f("thrust_impulse") velocity.x += dir.x * impulse @@ -357,6 +591,7 @@ func _physics_process(delta: float) -> void: _ability_active = false _active_ability = -1 _legs.set(&"charge_pitch_target", 0.0) + _legs.set(&"tail_ragdoll", false) # ── Mouse button single-thrust actions ─────────────────────────────────────── # Left only → thrust NE (forward-right diagonal) diff --git a/ps1_filter.gdshader.uid b/ps1_filter.gdshader.uid new file mode 100644 index 0000000..433b04b --- /dev/null +++ b/ps1_filter.gdshader.uid @@ -0,0 +1 @@ +uid://d3xyyy5bh0ma diff --git a/publikum_controller.gd.uid b/publikum_controller.gd.uid new file mode 100644 index 0000000..db00d94 --- /dev/null +++ b/publikum_controller.gd.uid @@ -0,0 +1 @@ +uid://bs682ey3p1ivj diff --git a/scene.tscn b/scene.tscn index d314e85..6d2e1a6 100644 --- a/scene.tscn +++ b/scene.tscn @@ -2,13 +2,13 @@ [ext_resource type="PackedScene" uid="uid://crtm0xtiql3r8" path="res://Player.tscn" id="1_ulcgi"] [ext_resource type="PackedScene" uid="uid://dio67r8ambe7h" path="res://Assets/arena_placeholder_v01.glb" id="2_nxogm"] -[ext_resource type="Script" uid="uid://8b1qil754yd3" path="res://matador_spawn.gd" id="3_spawn"] +[ext_resource type="Script" uid="uid://dou5ar6tkmng1" path="res://matador_spawn.gd" id="3_spawn"] [ext_resource type="Shader" uid="uid://d3xyyy5bh0ma" path="res://ps1_filter.gdshader" id="4_ps1shader"] [ext_resource type="PackedScene" uid="uid://cmxqocsdbgufr" path="res://Animations/mees_plaksutab.glb" id="5_m7jmp"] [ext_resource type="PackedScene" uid="uid://1y07gn65ktsi" path="res://Animations/ANIM_publik_mees.glb" id="7_xlvrw"] -[ext_resource type="Script" uid="uid://dr6phggarm73e" path="res://Animations/anim_publik_mees.gd" id="8_73fnb"] -[ext_resource type="Script" uid="uid://di0jafakftp3n" path="res://publikum_controller.gd" id="9_pubctrl"] -[ext_resource type="Script" uid="uid://xu6osmd62rj2" path="res://hud.gd" id="10_hud"] +[ext_resource type="Script" uid="uid://wj6tgh8nb0ka" path="res://Animations/anim_publik_mees.gd" id="8_73fnb"] +[ext_resource type="Script" uid="uid://bs682ey3p1ivj" path="res://publikum_controller.gd" id="9_pubctrl"] +[ext_resource type="Script" uid="uid://butd6b3tdwxrv" path="res://hud.gd" id="10_hud"] [sub_resource type="CameraAttributesPractical" id="CameraAttributesPractical_73fnb"] dof_blur_far_enabled = true diff --git a/tests/gameplay_test.gd.uid b/tests/gameplay_test.gd.uid new file mode 100644 index 0000000..e1740f0 --- /dev/null +++ b/tests/gameplay_test.gd.uid @@ -0,0 +1 @@ +uid://svqvri5xorqs diff --git a/tests/logic_test.gd.uid b/tests/logic_test.gd.uid new file mode 100644 index 0000000..8bb8206 --- /dev/null +++ b/tests/logic_test.gd.uid @@ -0,0 +1 @@ +uid://bmvvmkl7xctjn diff --git a/tests/ragdoll_throw_test.gd.uid b/tests/ragdoll_throw_test.gd.uid new file mode 100644 index 0000000..e01fbfe --- /dev/null +++ b/tests/ragdoll_throw_test.gd.uid @@ -0,0 +1 @@ +uid://ctwowq51ccqtg diff --git a/tests/screenshot_test.gd.uid b/tests/screenshot_test.gd.uid new file mode 100644 index 0000000..27aabad --- /dev/null +++ b/tests/screenshot_test.gd.uid @@ -0,0 +1 @@ +uid://gmw5pyavh5wu