From 44f91e28dee9dbe8217964b25145a6af327826df Mon Sep 17 00:00:00 2001 From: Davin <146634489+davin-christino@users.noreply.github.com> Date: Mon, 23 Mar 2026 17:35:21 +0530 Subject: [PATCH 1/3] ButtSlide Rewrite finally finished The Thing, trust me it's Fantastic. sorry for Dragging it for so long, this rewrite was Massive, but unlike the Low Taper this will never Fade. covered all bases (i think) except for 1. the animations, the offset variables aren't actually used, looks like. not experienced with the animation system in solar engine so i didn't bother touching it. 2. the weird bug when you fall off slopes when sliding at high speeds, although this happens in other states too so the bug might be a fundamental flaw with mario, not with this state. removing the first line in _on_enter makes it worse, this might be something to look into. --- entities/player/mario/mario.tscn | 12 +- .../player/shared/states/dry/butt_slide.gd | 225 ++++-------------- 2 files changed, 53 insertions(+), 184 deletions(-) diff --git a/entities/player/mario/mario.tscn b/entities/player/mario/mario.tscn index 2cdec33b..df6fd2c6 100644 --- a/entities/player/mario/mario.tscn +++ b/entities/player/mario/mario.tscn @@ -145,7 +145,7 @@ [ext_resource type="PackedScene" uid="uid://yxcrkjecabc2" path="res://props/particles/spin_ring.tscn" id="149_qbnhj"] [ext_resource type="Script" uid="uid://c6f05nyrdtcd6" path="res://entities/player/shared/states/dry/dive_states/super_rollout.gd" id="150_4duxu"] [ext_resource type="AudioStream" uid="uid://ckr28u3htxv4o" path="res://entities/player/shared/motion/final_hit.wav" id="150_m576x"] -[ext_resource type="Script" uid="uid://b7w0nkvq1wjk" path="res://entities/player/shared/states/dry/die.gd" id="150_ufl2i"] +[ext_resource type="Script" path="res://entities/player/shared/states/dry/die.gd" id="150_ufl2i"] [ext_resource type="Script" uid="uid://ftwidhx88kkq" path="res://entities/player/shared/fludd/fludd_manager.gd" id="151_4womg"] [ext_resource type="AudioStream" uid="uid://b1orysswk33x1" path="res://entities/player/mario/voice_sunshine/woah_ledge.wav" id="151_u7cu3"] [ext_resource type="AudioStream" uid="uid://l8n6ucspwj5v" path="res://entities/player/shared/sfx/too_bad.wav" id="152_2h0ab"] @@ -2981,15 +2981,11 @@ sfx_layers = Array[ExtResource("49_apkmk")]([SubResource("Resource_ujdp5"), SubR [node name="ButtSlide" type="Node" parent="StateManager/Dry" unique_id=720337721] script = ExtResource("140_lfmwr") -speed = 750.0 -min_speed = 300.0 +friction_coefficient_default = 0.15 +friction_coefficient_decel = 0.6 +accel_gravity_multiplier = 1.5 max_speed = 1200.0 min_remain_speed = 6.0 -friction = 7.5 -max_accel = 13.2 -turn_forgiveness = 1.5 -shallow_penalty = 0.25 -incline_friction = 90.0 animation_forward = &"butt_slide_forwards" animation_backward = &"butt_slide_backwards" animation_airborne = &"butt_slide_jump" diff --git a/entities/player/shared/states/dry/butt_slide.gd b/entities/player/shared/states/dry/butt_slide.gd index 453b990b..811d0eb2 100644 --- a/entities/player/shared/states/dry/butt_slide.gd +++ b/entities/player/shared/states/dry/butt_slide.gd @@ -2,30 +2,11 @@ class_name ButtSlide extends PlayerState ## Crouching while on a slope (or being forced.) -## Default sliding speed. -@export var speed: float = 10 -## Minimum sliding speed (through decelerating by holding the opposite direction you're sliding in.) -@export var min_speed: float = 5 -## Maximum sliding speed (through accelerating by holding the direction you're sliding in.) -@export var max_speed: float = 20 -## Minimum sliding speed necessary to remain in a buttslide state. -## (In practice: how much you'll be sliding on flat ground after sliding off a slope.) -@export var min_remain_speed: float = 0.1 - -## Friction applied when sliding along flat or shallow ground. -@export var friction: float = 0.125 - -## Maximum acceleration from sliding, when a slope is as steep as possible. -@export var max_accel: float = 0.22 - -## How much speed is lost when changing slope angle. -## Higher turn forgiveness means more speed is lost. -@export_exp_easing() var turn_forgiveness: float = 2.0 - -## Higher shallowness penalty means shallow slopes will decrease speed more. -@export_exp_easing() var shallow_penalty: float = 0.5 -## Higher friction means less speed conservation on steep slopes. -@export_exp_easing() var incline_friction: float = 10.0 +@export var friction_coefficient_default: float +@export var friction_coefficient_decel: float +@export var accel_gravity_multiplier: float +@export var max_speed: float +@export var min_remain_speed: float @export_category(&"Animation (Unique to State)") @export var animation_forward: StringName @@ -35,39 +16,29 @@ extends PlayerState @export var animation_airborne: StringName @export var anim_offset_a: Vector2 -## Speed at which the player slides. -var slide_speed: float = 0.0 - -## Stored previous direction, for changing slope angle. -var old_direction: Vector2 - -## True when the player does not have a slide direction yet. -var no_direction: bool - -var input_dir: int - func _on_enter(handover_speed): + # TODO: find out why this line is here. removing it causes some weird behaviour but idk why actor.set_floor_snap_length(movement.snap_length) - + + # Convert vertical speed from ground pounding into sliding speed if handover_speed is float: - old_direction = Vector2.DOWN - slide_speed = handover_speed - else: - no_direction = true - slide_speed = 0 + actor.velocity = (Vector2.DOWN * handover_speed).slide(actor.get_floor_normal()) func _physics_tick(delta: float): + # Apply physics if actor.is_on_floor(): _grounded(delta) else: _airborne(delta) - + + # Set animations _set_appropriate_anim() func _subsequent_ticks(_delta: float): + # Emit particles and play sound effects if actor.is_on_floor(): particles[0].emit_at(actor) @@ -79,168 +50,70 @@ func _subsequent_ticks(_delta: float): ## Buttsliding on the ground / slope. func _grounded(delta: float): - var floor_normal: Vector2 = actor.get_floor_normal() - - var slide_direction: Vector2 - - slide_direction = _get_slide_dir(floor_normal) - input_dir = InputManager.get_x_dir() - - if no_direction: - _apply_slide_direction(floor_normal, slide_direction) - else: - # If we're changing direction, redirect current sliding speed into the new direction - if not slide_direction.is_equal_approx(old_direction): - _redirect_slide(slide_direction, old_direction) - - # Modify slide_speed prior to setting velocity - _modify_speed(floor_normal) - - actor.velocity = slide_direction * slide_speed - actor.velocity.y += 6.0 * delta - - # Store the sliding direction so we can check for changes - old_direction = slide_direction + # Equal to 1 if accelerating, -1 if decelerating, 0 otherwise. + var accel_dir: int = InputManager.get_x_dir() * sign(actor.velocity.x) + # Coefficient of friction, should be increased when decelerating. + var friction: float = friction_coefficient_decel if accel_dir == -1 else friction_coefficient_default + # Acceleration due to sliding from gravity, should be increased when accelerating. + var slide_accel: float = movement.max_grav + if accel_dir == 1: slide_accel *= accel_gravity_multiplier + + # Apply gravity + actor.velocity += Vector2.DOWN.slide(actor.get_floor_normal()) * slide_accel * delta + + # Calculate normal acceleration + var normal_accel = Vector2.UP.dot(actor.get_floor_normal()) * slide_accel + + # Calculate frictional acceleration + actor.velocity = actor.velocity.move_toward(Vector2.ZERO, friction * normal_accel * delta) + + # Cap the speed + actor.velocity = actor.velocity.limit_length(max_speed) ## Buttsliding in the air. func _airborne(delta: float): - no_direction = true - slide_speed = 0 - movement.apply_gravity(delta) -## Get the slide direction downwards along the slope. -func _get_slide_dir(floor_normal: Vector2) -> Vector2: - var direction: Vector2 - - if floor_normal == Vector2.UP: - # On flat ground, just go right. - direction = Vector2.RIGHT - else: - direction = floor_normal.orthogonal() - - if direction.dot(Vector2.DOWN) < 0: - direction = -direction - - return direction - - -## Integrate current velocity and direction to a slide. -func _apply_slide_direction(floor_normal: Vector2, slide_direction: Vector2): - # If we have only just started sliding, - # we need to convert the player's velocity into sliding speed. - if floor_normal == Vector2.UP: - slide_speed = actor.velocity.x - else: - if abs(actor.velocity.x) > abs(actor.velocity.dot(slide_direction)): - slide_speed = actor.velocity.x * sign(floor_normal.x) - else: - slide_speed = actor.velocity.dot(slide_direction) - - no_direction = false - - -## Calculates acceleration, deceleration, and target speed; then applies them. -func _modify_speed(floor_normal: Vector2): - # How flat the floor is, 0-1 - var flatness: float = floor_normal.dot(Vector2.UP) - # How steep the floor is (opposite of flatness, just for convenience) - var steepness: float = 1 - flatness - var slope_dir: int = sign(floor_normal.x) - - var accel_ease: float = ease(steepness, shallow_penalty) - - var slide_accel: float = accel_ease * max_accel - var slide_decel: float = ease(flatness, incline_friction) * friction - - var target_speed: float = accel_ease * speed - - if input_dir != 0: - # Holding the direction of the slope (accel) - if input_dir == slope_dir: - target_speed = accel_ease * max_speed - # Holding the opposite direction of the slope (decel) - elif input_dir == -slope_dir: - target_speed = accel_ease * min_speed - - slide_decel = max(slide_decel, 6.0) - - # Accelerate down the slope - _accelerate(slide_accel, target_speed) - # Decelerate due to friction - _decelerate(slide_decel, target_speed) - - -func _redirect_slide(new: Vector2, old: Vector2): - # Calculate how similar the new direction is to the old direction - var preserved = new.dot(old) - - # Store the sign: -1 if we have moved from an upward slope to a downward slope - # or vice versa - var new_sign = sign(preserved) - - # Take absolute value so we can work with 0 to 1 instead of -1 to 1 - preserved = abs(preserved) - - # Calculate how much speed would be lost - var lost = 1 - preserved - # Apply forgiveness to what was lost - var lost_forgiven = ease(lost, turn_forgiveness) - - # Subtract the reduced loss from 1 - var final_preserved = 1 - lost_forgiven - - slide_speed *= final_preserved * new_sign - - -func _accelerate(amount: Variant, speed_cap: float): - if slide_speed + amount < speed_cap: - slide_speed += amount - elif slide_speed < speed_cap: - slide_speed = speed_cap - - -func _decelerate(amount: float, target: float): - var direction = sign(slide_speed) - var abs_speed = abs(slide_speed) - - if abs_speed > target: - abs_speed = max(abs_speed - amount, target) - - slide_speed = abs_speed * direction - - ## Set the animation based on how you're moving on a slope. func _set_appropriate_anim(): + # Play airborne animation if not on floor if not actor.is_on_floor(): actor.doll.play(animation_airborne) return - if input_dir != 0: + + # Play moving forward/backward if left/right is held. + if InputManager.get_x_dir() != 0: actor.doll.play( - animation_forward if input_dir == movement.facing_direction else animation_backward + animation_forward if InputManager.get_x_dir() == movement.facing_direction else animation_backward ) return + + # Play default animation otherwise. actor.doll.play(animation_data.animation) func _trans_rules(): + # When slow enough on flat ground, exit the sliding state. if not movement.is_slide_slope() and abs(actor.velocity.x) < min_remain_speed: - return [&"Crouch", [true, false]] + if Input.is_action_pressed(&"down"): + return [&"Crouch", [true, false]] + else: + return &"Idle" - if not Input.is_action_pressed(&"down"): + # Exit the sliding state when up is pressed. + if input.buffered_input(&"up"): if actor.is_on_floor(): - if old_direction.y == 0 and input_dir != 0 or Input.is_action_just_pressed(&"up"): - return &"Idle" - if input_dir == -sign(old_direction.x): - return &"Walk" + return &"Idle" else: return &"Fall" + # Jump out of a buttslide: if actor.is_on_floor() and input.buffered_input(&"jump"): return &"ButtSlideJump" + # Spin out of a buttslide: if input.buffered_input(&"spin"): return &"Spin" From 5a5390c02a6db96954ee3fc7ca9c972ac25e81f8 Mon Sep 17 00:00:00 2001 From: Charpurrr <66517745+Charpurrr@users.noreply.github.com> Date: Tue, 24 Mar 2026 14:42:59 +0100 Subject: [PATCH 2/3] Animations and Documentation Also removes all instances of snap length being set in other states because that had no effect. Still need to find a way to make Mario stick to slopes when going up them. --- entities/player/mario/mario.tscn | 141 +++++++++++++++--- entities/player/shared/player_movement.gd | 2 - .../shared/states/dry/airborne/airborne.gd | 2 - .../player/shared/states/dry/butt_slide.gd | 63 ++++---- .../shared/states/dry/dive_states/dive.gd | 1 - .../shared/states/dry/grounded/grounded.gd | 2 - 6 files changed, 155 insertions(+), 56 deletions(-) diff --git a/entities/player/mario/mario.tscn b/entities/player/mario/mario.tscn index df6fd2c6..f4d59ee1 100644 --- a/entities/player/mario/mario.tscn +++ b/entities/player/mario/mario.tscn @@ -145,7 +145,7 @@ [ext_resource type="PackedScene" uid="uid://yxcrkjecabc2" path="res://props/particles/spin_ring.tscn" id="149_qbnhj"] [ext_resource type="Script" uid="uid://c6f05nyrdtcd6" path="res://entities/player/shared/states/dry/dive_states/super_rollout.gd" id="150_4duxu"] [ext_resource type="AudioStream" uid="uid://ckr28u3htxv4o" path="res://entities/player/shared/motion/final_hit.wav" id="150_m576x"] -[ext_resource type="Script" path="res://entities/player/shared/states/dry/die.gd" id="150_ufl2i"] +[ext_resource type="Script" uid="uid://b7w0nkvq1wjk" path="res://entities/player/shared/states/dry/die.gd" id="150_ufl2i"] [ext_resource type="Script" uid="uid://ftwidhx88kkq" path="res://entities/player/shared/fludd/fludd_manager.gd" id="151_4womg"] [ext_resource type="AudioStream" uid="uid://b1orysswk33x1" path="res://entities/player/mario/voice_sunshine/woah_ledge.wav" id="151_u7cu3"] [ext_resource type="AudioStream" uid="uid://l8n6ucspwj5v" path="res://entities/player/shared/sfx/too_bad.wav" id="152_2h0ab"] @@ -440,7 +440,7 @@ animations = [{ "speed": 5.0 }] -[sub_resource type="Resource" id="Resource_nxfaa"] +[sub_resource type="Resource" id="Resource_kuq6s"] resource_local_to_scene = true script = ExtResource("23_bbld7") doll_path = NodePath("Doll") @@ -450,19 +450,19 @@ frame_offsets = Dictionary[int, Vector2i]({ 0: Vector2i(0, 0) }) frame_fludd = Dictionary[int, String]({ -0: "rot_y090", -1: "rot_y090" +0: "default" }) frame_fludd_offsets = Dictionary[int, Vector2i]({ -0: Vector2i(1, 1), -1: Vector2i(1, 2) +0: Vector2i(0, 6), +1: Vector2i(0, 7) }) -animation = "die" +animation = "butt_slide_forwards" frame = 0 -preview = false +preview = true +preview_fludd = false frame_offset = Vector2i(0, 0) -fludd_animation = "rot_y090" -fludd_offset = Vector2i(1, 1) +fludd_animation = "default" +fludd_offset = Vector2i(0, 6) metadata/_custom_type_script = "uid://cb4g1yl24gj7m" [sub_resource type="AtlasTexture" id="AtlasTexture_f3xbj"] @@ -1774,15 +1774,15 @@ frame_fludd = Dictionary[int, String]({ 0: "default" }) frame_fludd_offsets = Dictionary[int, Vector2i]({ -0: Vector2i(0, 5), -1: Vector2i(0, 6) +0: Vector2i(0, 6), +1: Vector2i(0, 7) }) animation = "butt_slide_jump" frame = 0 preview = false frame_offset = Vector2i(0, 3) fludd_animation = "default" -fludd_offset = Vector2i(0, 5) +fludd_offset = Vector2i(0, 6) metadata/_custom_type_script = "uid://cb4g1yl24gj7m" [sub_resource type="Resource" id="Resource_jo8kb"] @@ -2306,6 +2306,76 @@ overwrite_other = false cutoff_sfx = false metadata/_custom_type_script = "uid://dvlt5sb8enmu8" +[sub_resource type="Resource" id="Resource_msjg8"] +resource_local_to_scene = true +script = ExtResource("23_bbld7") +doll_path = NodePath("Doll") +fludd_f_path = NodePath("FluddInfront") +fludd_b_path = NodePath("FluddBehind") +frame_offsets = Dictionary[int, Vector2i]({ +0: Vector2i(0, 0) +}) +frame_fludd_offsets = Dictionary[int, Vector2i]({ +0: Vector2i(0, 6), +1: Vector2i(0, 7) +}) +animation = "butt_slide" +frame = 0 +preview = false +frame_offset = Vector2i(0, 0) +fludd_animation = "default" +fludd_offset = Vector2i(0, 6) +metadata/_custom_type_script = "uid://cb4g1yl24gj7m" + +[sub_resource type="Resource" id="Resource_rev7q"] +resource_local_to_scene = true +script = ExtResource("23_bbld7") +doll_path = NodePath("Doll") +fludd_f_path = NodePath("FluddInfront") +fludd_b_path = NodePath("FluddBehind") +frame_offsets = Dictionary[int, Vector2i]({ +0: Vector2i(0, 0) +}) +frame_fludd = Dictionary[int, String]({ +0: "default" +}) +frame_fludd_offsets = Dictionary[int, Vector2i]({ +0: Vector2i(0, 6), +1: Vector2i(0, 7) +}) +animation = "butt_slide_backwards" +frame = 0 +preview = false +frame_offset = Vector2i(0, 0) +fludd_animation = "default" +fludd_offset = Vector2i(0, 6) +metadata/_custom_type_script = "uid://cb4g1yl24gj7m" + +[sub_resource type="Resource" id="Resource_ddfva"] +resource_local_to_scene = true +script = ExtResource("23_bbld7") +doll_path = NodePath("Doll") +fludd_f_path = NodePath("FluddInfront") +fludd_b_path = NodePath("FluddBehind") +frame_offsets = Dictionary[int, Vector2i]({ +0: Vector2i(0, 3), +1: Vector2i(0, 3) +}) +frame_fludd = Dictionary[int, String]({ +0: "default" +}) +frame_fludd_offsets = Dictionary[int, Vector2i]({ +0: Vector2i(0, 6), +1: Vector2i(0, 7) +}) +animation = "butt_slide_jump" +frame = 0 +preview = false +frame_offset = Vector2i(0, 3) +fludd_animation = "default" +fludd_offset = Vector2i(0, 6) +metadata/_custom_type_script = "uid://cb4g1yl24gj7m" + [sub_resource type="Resource" id="Resource_ifrah"] resource_local_to_scene = true script = ExtResource("23_bbld7") @@ -2403,6 +2473,31 @@ fludd_animation = "default" fludd_offset = Vector2i(0, 0) metadata/_custom_type_script = "uid://cb4g1yl24gj7m" +[sub_resource type="Resource" id="Resource_nxfaa"] +resource_local_to_scene = true +script = ExtResource("23_bbld7") +doll_path = NodePath("Doll") +fludd_f_path = NodePath("FluddInfront") +fludd_b_path = NodePath("FluddBehind") +frame_offsets = Dictionary[int, Vector2i]({ +0: Vector2i(0, 0) +}) +frame_fludd = Dictionary[int, String]({ +0: "rot_y090", +1: "rot_y090" +}) +frame_fludd_offsets = Dictionary[int, Vector2i]({ +0: Vector2i(1, 1), +1: Vector2i(1, 2) +}) +animation = "die" +frame = 0 +preview = false +frame_offset = Vector2i(0, 0) +fludd_animation = "rot_y090" +fludd_offset = Vector2i(1, 1) +metadata/_custom_type_script = "uid://cb4g1yl24gj7m" + [sub_resource type="Resource" id="Resource_cux1t"] script = ExtResource("49_apkmk") sfx_list = [ExtResource("152_2h0ab")] @@ -2448,19 +2543,17 @@ offset_bottom = -33.0 visible = false position = Vector2(0, -24) sprite_frames = SubResource("SpriteFrames_e1ut2") -animation = &"rot_y090" [node name="Doll" type="AnimatedSprite2D" parent="." unique_id=1876045562] position = Vector2(0, -24) sprite_frames = ExtResource("4_xenv0") -animation = &"die" -metadata/last_previewed = SubResource("Resource_nxfaa") +animation = &"butt_slide_forwards" +metadata/last_previewed = SubResource("Resource_kuq6s") [node name="FluddInfront" type="AnimatedSprite2D" parent="." unique_id=1928286412] visible = false position = Vector2(0, -24) sprite_frames = SubResource("SpriteFrames_1i10v") -animation = &"rot_y090" [node name="Hitbox" type="CollisionShape2D" parent="." unique_id=76578262] position = Vector2(0, -15) @@ -2604,7 +2697,6 @@ max_speed = 180.0 term_vel = 480.0 min_grav = 774.0 max_grav = 792.0 -snap_length = 8.0 swim_speed = 180.0 min_slide_incline = 0.4 @@ -2981,14 +3073,15 @@ sfx_layers = Array[ExtResource("49_apkmk")]([SubResource("Resource_ujdp5"), SubR [node name="ButtSlide" type="Node" parent="StateManager/Dry" unique_id=720337721] script = ExtResource("140_lfmwr") -friction_coefficient_default = 0.15 -friction_coefficient_decel = 0.6 +friction_coefficient_default = 0.3 +friction_coefficient_decel = 0.7 accel_gravity_multiplier = 1.5 -max_speed = 1200.0 +max_speed = 300.0 min_remain_speed = 6.0 -animation_forward = &"butt_slide_forwards" -animation_backward = &"butt_slide_backwards" -animation_airborne = &"butt_slide_jump" +default_animation_data = SubResource("Resource_msjg8") +forward_animation_data = SubResource("Resource_kuq6s") +backward_animation_data = SubResource("Resource_rev7q") +airborne_animation_data = SubResource("Resource_ddfva") hitbox_type = "Small" animation_data = SubResource("Resource_ifrah") particles = Array[ExtResource("55_bxnxc")]([SubResource("Resource_d3rr6")]) diff --git a/entities/player/shared/player_movement.gd b/entities/player/shared/player_movement.gd index 41fbea1e..a250dfb2 100644 --- a/entities/player/shared/player_movement.gd +++ b/entities/player/shared/player_movement.gd @@ -48,8 +48,6 @@ var return_timer: float ## Amount of units the player needs to be above the ground to perform an airborne action. @export var air_margin: int = 10 -## Sets the floor_snap_length of the actor. -@export var snap_length: float = 16 ## The y position of the point you walljumped from. ## Used to avoid being able to scale a wall infinitely. diff --git a/entities/player/shared/states/dry/airborne/airborne.gd b/entities/player/shared/states/dry/airborne/airborne.gd index a794bac7..63e449df 100644 --- a/entities/player/shared/states/dry/airborne/airborne.gd +++ b/entities/player/shared/states/dry/airborne/airborne.gd @@ -4,8 +4,6 @@ extends PlayerState func _physics_tick(_delta: float): - actor.set_floor_snap_length(0.0) - actor.stomp_hurtbox.monitoring = actor.velocity.y > 0 if actor.is_on_ceiling() and actor.velocity.y < 0 and not live_substate is GroundPound: diff --git a/entities/player/shared/states/dry/butt_slide.gd b/entities/player/shared/states/dry/butt_slide.gd index 811d0eb2..db8a72b8 100644 --- a/entities/player/shared/states/dry/butt_slide.gd +++ b/entities/player/shared/states/dry/butt_slide.gd @@ -1,26 +1,37 @@ class_name ButtSlide extends PlayerState -## Crouching while on a slope (or being forced.) +## Crouching while on a slope. +## See [member CharacterBody2D.floor_snap_length]. +@export var floor_snap_length: float = 32.0 +## The default frictional coefficient when not accelerating or decelerating. @export var friction_coefficient_default: float +## The frictional coefficient when holding against the direction you're sliding in. +## (Uphill) @export var friction_coefficient_decel: float +## The gravity multiplier when holding the direction you're sliding in. +## (Downhill) @export var accel_gravity_multiplier: float +## How quickly you can slide. @export var max_speed: float +## How much speed the [Player] @export var min_remain_speed: float @export_category(&"Animation (Unique to State)") -@export var animation_forward: StringName -@export var anim_offset_f: Vector2 -@export var animation_backward: StringName -@export var anim_offset_b: Vector2 -@export var animation_airborne: StringName -@export var anim_offset_a: Vector2 +## Animation used by default. +@export var default_animation_data: PStateAnimData +## Animation used when holding downhill. +@export var forward_animation_data: PStateAnimData +## Animation used when holding uphill. +@export var backward_animation_data: PStateAnimData +## Animation used when sliding off a ledge. +## Not to be confused with [ButtSlideJump]. +@export var airborne_animation_data: PStateAnimData func _on_enter(handover_speed): - # TODO: find out why this line is here. removing it causes some weird behaviour but idk why - actor.set_floor_snap_length(movement.snap_length) - + actor.set_floor_snap_length(floor_snap_length) + # Convert vertical speed from ground pounding into sliding speed if handover_speed is float: actor.velocity = (Vector2.DOWN * handover_speed).slide(actor.get_floor_normal()) @@ -57,16 +68,16 @@ func _grounded(delta: float): # Acceleration due to sliding from gravity, should be increased when accelerating. var slide_accel: float = movement.max_grav if accel_dir == 1: slide_accel *= accel_gravity_multiplier - + # Apply gravity actor.velocity += Vector2.DOWN.slide(actor.get_floor_normal()) * slide_accel * delta - + # Calculate normal acceleration var normal_accel = Vector2.UP.dot(actor.get_floor_normal()) * slide_accel - + # Calculate frictional acceleration actor.velocity = actor.velocity.move_toward(Vector2.ZERO, friction * normal_accel * delta) - + # Cap the speed actor.velocity = actor.velocity.limit_length(max_speed) @@ -80,18 +91,20 @@ func _airborne(delta: float): func _set_appropriate_anim(): # Play airborne animation if not on floor if not actor.is_on_floor(): - actor.doll.play(animation_airborne) - return - - # Play moving forward/backward if left/right is held. - if InputManager.get_x_dir() != 0: - actor.doll.play( - animation_forward if InputManager.get_x_dir() == movement.facing_direction else animation_backward - ) + overwrite_animation(airborne_animation_data) return - - # Play default animation otherwise. - actor.doll.play(animation_data.animation) + + var x_dir := InputManager.get_x_dir() + + # Play forwards animation when moving in the same direction as the slide + if x_dir == movement.facing_direction: + overwrite_animation(forward_animation_data) + # Play backwards animation when moving in opposite direction as the slide + elif x_dir == -movement.facing_direction: + overwrite_animation(backward_animation_data) + # Play normal slide animation + else: + overwrite_animation(default_animation_data) func _trans_rules(): diff --git a/entities/player/shared/states/dry/dive_states/dive.gd b/entities/player/shared/states/dry/dive_states/dive.gd index 4337a6cc..fe9bb18e 100644 --- a/entities/player/shared/states/dry/dive_states/dive.gd +++ b/entities/player/shared/states/dry/dive_states/dive.gd @@ -25,7 +25,6 @@ func _on_enter(dive_direction): movement.consec_jumps = 0 movement.dived = true - actor.set_floor_snap_length(movement.snap_length) actor.dive_hurtbox.monitoring = true if actor.is_on_floor(): diff --git a/entities/player/shared/states/dry/grounded/grounded.gd b/entities/player/shared/states/dry/grounded/grounded.gd index afc0176f..a47d1c24 100644 --- a/entities/player/shared/states/dry/grounded/grounded.gd +++ b/entities/player/shared/states/dry/grounded/grounded.gd @@ -9,8 +9,6 @@ func _on_enter(play_land_sfx): movement.air_spun = false movement.dived = false - actor.set_floor_snap_length(movement.snap_length) - if play_land_sfx: # Normal footsteps sfx_layers[0].play_sfx_at(self) From 58fe0068ca85383913021e47f0f068ffd66301ad Mon Sep 17 00:00:00 2001 From: Davin <146634489+davin-christino@users.noreply.github.com> Date: Mon, 6 Apr 2026 22:28:59 +0530 Subject: [PATCH 3/3] new buttslide system direction now affects maxspeed not friction. feels pretty good to play i'd say. --- entities/player/mario/mario.tscn | 7 +-- .../player/shared/states/dry/butt_slide.gd | 51 ++++++++++++------- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/entities/player/mario/mario.tscn b/entities/player/mario/mario.tscn index f4d59ee1..84a56f2d 100644 --- a/entities/player/mario/mario.tscn +++ b/entities/player/mario/mario.tscn @@ -458,8 +458,7 @@ frame_fludd_offsets = Dictionary[int, Vector2i]({ }) animation = "butt_slide_forwards" frame = 0 -preview = true -preview_fludd = false +preview = false frame_offset = Vector2i(0, 0) fludd_animation = "default" fludd_offset = Vector2i(0, 6) @@ -3074,9 +3073,11 @@ sfx_layers = Array[ExtResource("49_apkmk")]([SubResource("Resource_ujdp5"), SubR [node name="ButtSlide" type="Node" parent="StateManager/Dry" unique_id=720337721] script = ExtResource("140_lfmwr") friction_coefficient_default = 0.3 -friction_coefficient_decel = 0.7 +friction_coefficient_overspeed = 1.4 accel_gravity_multiplier = 1.5 +max_speed_decel = 150.0 max_speed = 300.0 +max_speed_accel = 500.0 min_remain_speed = 6.0 default_animation_data = SubResource("Resource_msjg8") forward_animation_data = SubResource("Resource_kuq6s") diff --git a/entities/player/shared/states/dry/butt_slide.gd b/entities/player/shared/states/dry/butt_slide.gd index db8a72b8..4af5f5f2 100644 --- a/entities/player/shared/states/dry/butt_slide.gd +++ b/entities/player/shared/states/dry/butt_slide.gd @@ -4,17 +4,21 @@ extends PlayerState ## See [member CharacterBody2D.floor_snap_length]. @export var floor_snap_length: float = 32.0 -## The default frictional coefficient when not accelerating or decelerating. +## The default frictional coefficient @export var friction_coefficient_default: float -## The frictional coefficient when holding against the direction you're sliding in. -## (Uphill) -@export var friction_coefficient_decel: float +## The frictional coefficient when over the maximum speed. +@export var friction_coefficient_overspeed: float ## The gravity multiplier when holding the direction you're sliding in. -## (Downhill) @export var accel_gravity_multiplier: float -## How quickly you can slide. + +## How quickly you can slide when decelerating. +@export var max_speed_decel: float +## How quickly you can slide when not accelerating or decelerating. @export var max_speed: float -## How much speed the [Player] +## How quickly you can slide when accelerating. +@export var max_speed_accel: float + +## How much speed the [Player] needs to remain in a sliding state. @export var min_remain_speed: float @export_category(&"Animation (Unique to State)") @@ -63,11 +67,21 @@ func _subsequent_ticks(_delta: float): func _grounded(delta: float): # Equal to 1 if accelerating, -1 if decelerating, 0 otherwise. var accel_dir: int = InputManager.get_x_dir() * sign(actor.velocity.x) - # Coefficient of friction, should be increased when decelerating. - var friction: float = friction_coefficient_decel if accel_dir == -1 else friction_coefficient_default - # Acceleration due to sliding from gravity, should be increased when accelerating. - var slide_accel: float = movement.max_grav - if accel_dir == 1: slide_accel *= accel_gravity_multiplier + + var slide_accel: float + var speed_limit: float + var friction: float = friction_coefficient_default + var overspeed_friction: float = friction_coefficient_overspeed + match accel_dir: + -1: # decelerating + slide_accel = movement.max_grav + speed_limit = max_speed_decel + 0: # not holding a direction + slide_accel = movement.max_grav + speed_limit = max_speed + 1: # accelerating + slide_accel = movement.max_grav * accel_gravity_multiplier + speed_limit = max_speed_accel # Apply gravity actor.velocity += Vector2.DOWN.slide(actor.get_floor_normal()) * slide_accel * delta @@ -75,11 +89,14 @@ func _grounded(delta: float): # Calculate normal acceleration var normal_accel = Vector2.UP.dot(actor.get_floor_normal()) * slide_accel - # Calculate frictional acceleration - actor.velocity = actor.velocity.move_toward(Vector2.ZERO, friction * normal_accel * delta) - - # Cap the speed - actor.velocity = actor.velocity.limit_length(max_speed) + # Check if under the speed limit: + if actor.velocity.length() <= speed_limit: + # If yes, apply regular friction + actor.velocity = actor.velocity.move_toward(Vector2.ZERO, friction * normal_accel * delta) + else: + # If no, apply overspeed friction. Speed should not go below the speed limit. + actor.velocity = actor.velocity.move_toward(actor.velocity.limit_length(speed_limit), + overspeed_friction * normal_accel * delta) ## Buttsliding in the air.