Merge remote-tracking branch 'upstream/main' into pulls/small-crouch-hitbox-fix

This commit is contained in:
KirbyKidJ
2025-09-26 10:51:17 -07:00
128 changed files with 14908 additions and 11655 deletions

View File

@@ -1,24 +1,41 @@
class_name Player
extends CharacterBody2D
var AIR_ACCEL := 3.0
var AIR_SKID := 1.5
var DECEL := 3.0
var FALL_GRAVITY := 25.0
var GROUND_RUN_ACCEL := 1.25
var GROUND_WALK_ACCEL := 4.0
var JUMP_GRAVITY := 11.0
var JUMP_HEIGHT := 300.0
var JUMP_INCR := 8.0
var SWIM_GRAVITY := 2.5
var SWIM_SPEED := 95.0
var MAX_FALL_SPEED := 280
var MAX_SWIM_FALL_SPEED := 200
var RUN_SKID := 8.0
var RUN_SPEED := 160
var WALK_SKID := 8.0
var WALK_SPEED := 96.0
var CEILING_BUMP_SPEED := 45.0
#region Physics properies, these can be changed within a custom character's CharacterInfo.json
var JUMP_GRAVITY := 11.0 # The player's gravity while jumping, measured in px/frame
var JUMP_HEIGHT := 300.0 # The strength of the player's jump, measured in px/sec
var JUMP_INCR := 8.0 # How much the player's X velocity affects their jump speed
var JUMP_CANCEL_DIVIDE := 1.5 # When the player cancels their jump, their Y velocity gets divided by this value
var JUMP_HOLD_SPEED_THRESHOLD := 0.0 # When the player's Y velocity goes past this value while jumping, their gravity switches to FALL_GRAVITY
var BOUNCE_HEIGHT := 200.0 # The strength at which the player bounces off enemies, measured in px/sec
var BOUNCE_JUMP_HEIGHT := 300.0 # The strength at which the player bounces off enemies while holding jump, measured in px/sec
var FALL_GRAVITY := 25.0 # The player's gravity while falling, measured in px/frame
var MAX_FALL_SPEED := 280.0 # The player's maximum fall speed, measured in px/sec
var CEILING_BUMP_SPEED := 45.0 # The speed at which the player falls after hitting a ceiling, measured in px/sec
var WALK_SPEED := 96.0 # The player's speed while walking, measured in px/sec
var GROUND_WALK_ACCEL := 4.0 # The player's acceleration while walking, measured in px/frame
var WALK_SKID := 8.0 # The player's turning deceleration while running, measured in px/frame
var RUN_SPEED := 160.0 # The player's speed while running, measured in px/sec
var GROUND_RUN_ACCEL := 1.25 # The player's acceleration while running, measured in px/frame
var RUN_SKID := 8.0 # The player's turning deceleration while running, measured in px/frame
var DECEL := 3.0 # The player's deceleration while no buttons are pressed, measured in px/frame
var AIR_ACCEL := 3.0 # The player's acceleration while in midair, measured in px/frame
var AIR_SKID := 1.5 # The player's turning deceleration while in midair, measured in px/frame
var SWIM_SPEED := 95.0 # The player's horizontal speed while swimming, measured in px/sec
var SWIM_GROUND_SPEED := 45.0 # The player's horizontal speed while grounded underwater, measured in px/sec
var SWIM_HEIGHT := 100.0 # The strength of the player's swim, measured in px/sec
var SWIM_GRAVITY := 2.5 # The player's gravity while swimming, measured in px/frame
var MAX_SWIM_FALL_SPEED := 200.0 # The player's maximum fall speed while swimming, measured in px/sec
var DEATH_JUMP_HEIGHT := 300.0 # The strength of the player's "jump" during the death animation, measured in px/sec
#endregion
@onready var camera_center_joint: Node2D = $CameraCenterJoint
@onready var sprite: AnimatedSprite2D = %Sprite
@@ -57,6 +74,8 @@ var pipe_move_direction := 1
var stomp_combo := 0
var is_invincible := false
var can_pose := false
var is_posing := false
const COMBO_VALS := [100, 200, 400, 500, 800, 1000, 2000, 4000, 5000, 8000, null]
@@ -125,7 +144,7 @@ const ANIMATION_FALLBACKS := {
"WaterIdle": "Idle",
"DieFreeze": "Die",
"StarJump": "Jump",
"StarFall": "JumpFall"
"StarFall": "StarJump"
}
var palette_transform := true
@@ -272,12 +291,8 @@ func apply_gravity(delta: float) -> void:
if in_water or flight_meter > 0:
gravity = SWIM_GRAVITY
else:
if gravity_vector.y > 0:
if velocity.y > 0:
gravity = FALL_GRAVITY
elif gravity_vector.y < 0:
if velocity.y < 0:
gravity = FALL_GRAVITY
if sign(gravity_vector.y) * velocity.y + JUMP_HOLD_SPEED_THRESHOLD > 0.0:
gravity = FALL_GRAVITY
velocity += (gravity_vector * ((gravity / (1.5 if low_gravity else 1.0)) / delta)) * delta
var target_fall: float = MAX_FALL_SPEED
if in_water:
@@ -363,30 +378,32 @@ func is_actually_on_ceiling() -> bool:
return true
return false
func enemy_bounce_off(add_combo := true) -> void:
func enemy_bounce_off(add_combo := true, award_score := true) -> void:
if add_combo:
add_stomp_combo()
add_stomp_combo(award_score)
jump_cancelled = not Global.player_action_pressed("jump", player_id)
await get_tree().physics_frame
if Global.player_action_pressed("jump", player_id):
velocity.y = -300
velocity.y = sign(gravity_vector.y) * -BOUNCE_JUMP_HEIGHT
gravity = JUMP_GRAVITY
has_jumped = true
else:
velocity.y = -200
velocity.y = sign(gravity_vector.y) * -BOUNCE_HEIGHT
func add_stomp_combo() -> void:
func add_stomp_combo(award_score := true) -> void:
if stomp_combo >= 10:
if Global.current_game_mode == Global.GameMode.CHALLENGE or Settings.file.difficulty.inf_lives:
Global.score += 10000
score_note_spawner.spawn_note(10000)
else:
Global.lives += 1
AudioManager.play_global_sfx("1_up")
score_note_spawner.spawn_one_up_note()
if award_score:
if Global.current_game_mode == Global.GameMode.CHALLENGE or Settings.file.difficulty.inf_lives:
Global.score += 10000
score_note_spawner.spawn_note(10000)
else:
Global.lives += 1
AudioManager.play_global_sfx("1_up")
score_note_spawner.spawn_one_up_note()
else:
Global.score += COMBO_VALS[stomp_combo]
score_note_spawner.spawn_note(COMBO_VALS[stomp_combo])
if award_score:
Global.score += COMBO_VALS[stomp_combo]
score_note_spawner.spawn_note(COMBO_VALS[stomp_combo])
stomp_combo += 1
func bump_ceiling() -> void:
@@ -528,6 +545,7 @@ func die(pit := false) -> void:
Global.p_switch_active = false
Global.p_switch_timer = 0
stop_all_timers()
sprite.process_mode = Node.PROCESS_MODE_ALWAYS
state_machine.transition_to("Dead", {"Pit": pit})
process_mode = Node.PROCESS_MODE_ALWAYS
get_tree().paused = true
@@ -545,34 +563,56 @@ func die(pit := false) -> void:
func death_load() -> void:
power_state = get_node("PowerStates/Small")
Global.player_power_states = "0000"
if Global.death_load:
return
Global.death_load = true
if Global.current_game_mode == Global.GameMode.CUSTOM_LEVEL:
LevelTransition.level_to_transition_to = "res://Scenes/Levels/LevelEditor.tscn"
Global.transition_to_scene("res://Scenes/Levels/LevelTransition.tscn")
return
if Global.current_game_mode == Global.GameMode.LEVEL_EDITOR:
owner.stop_testing()
return
# Handle lives decrement for CAMPAIGN and MARATHON
if [Global.GameMode.CAMPAIGN, Global.GameMode.MARATHON].has(Global.current_game_mode):
if Settings.file.difficulty.inf_lives == 0:
Global.lives -= 1
Global.death_load = true
if Global.current_game_mode == Global.GameMode.CHALLENGE:
Global.transition_to_scene("res://Scenes/Levels/ChallengeMiss.tscn")
elif Global.time <= 0:
Global.transition_to_scene("res://Scenes/Levels/TimeUp.tscn")
elif Global.lives <= 0 and Settings.file.difficulty.inf_lives == 0:
Global.death_load = false
Global.transition_to_scene("res://Scenes/Levels/GameOver.tscn")
else:
LevelPersistance.reset_states()
if Global.current_game_mode == Global.GameMode.BOO_RACE:
# Full dispatch table for death handling
var death_actions = {
Global.GameMode.CUSTOM_LEVEL: func():
LevelTransition.level_to_transition_to = "res://Scenes/Levels/LevelEditor.tscn"
Global.transition_to_scene("res://Scenes/Levels/LevelTransition.tscn"),
Global.GameMode.LEVEL_EDITOR: func():
owner.stop_testing(),
Global.GameMode.CHALLENGE: func():
Global.transition_to_scene("res://Scenes/Levels/ChallengeMiss.tscn"),
Global.GameMode.BOO_RACE: func():
Global.reset_values()
Global.clear_saved_values()
Global.death_load = false
Level.start_level_path = Global.current_level.scene_file_path
Global.current_level.reload_level()
Global.current_level.reload_level(),
"time_up": func():
Global.transition_to_scene("res://Scenes/Levels/TimeUp.tscn"),
"game_over": func():
Global.death_load = false
Global.transition_to_scene("res://Scenes/Levels/GameOver.tscn"),
"default_reload": func():
LevelPersistance.reset_states()
Global.current_level.reload_level()
}
# Determine which action to take
if death_actions.has(Global.current_game_mode):
death_actions[Global.current_game_mode].call()
elif Global.time <= 0:
death_actions["time_up"].call()
elif Global.lives <= 0 and Settings.file.difficulty.inf_lives == 0:
death_actions["game_over"].call()
else:
death_actions["default_reload"].call()
func time_up() -> void:
die()
@@ -583,6 +623,8 @@ func set_power_state_frame() -> void:
if power_state != null:
$ResourceSetterNew.resource_json = load(get_character_sprite_path())
$ResourceSetterNew.update_resource()
if %Sprite.sprite_frames != null:
can_pose = %Sprite.sprite_frames.has_animation("PoseDoor")
func get_power_up(power_name := "") -> void:
if is_dead:
@@ -652,7 +694,7 @@ func power_up_animation(new_power_state := "") -> void:
await get_tree().create_timer(0.6).timeout
transforming = false
get_tree().paused = false
sprite.process_mode = Node.PROCESS_MODE_PAUSABLE
sprite.process_mode = Node.PROCESS_MODE_INHERIT
if Global.player_action_just_pressed("jump", player_id):
jump()
return