mirror of
https://github.com/JHDev2006/Super-Mario-Bros.-Remastered-Public.git
synced 2025-10-22 15:38:14 +00:00
Merge remote-tracking branch 'upstream/main' into pulls/small-crouch-hitbox-fix
This commit is contained in:
@@ -10,6 +10,8 @@ var fly_wave := PI
|
||||
|
||||
var dead := false
|
||||
|
||||
var times_kicked := 0 ## For anti-infinite scoring in Challenge mode
|
||||
|
||||
func _ready() -> void:
|
||||
if has_meta("fly_2"):
|
||||
fly_wave = 0
|
||||
@@ -64,6 +66,7 @@ func summon_shell(flipped := false, launch := false) -> void:
|
||||
DiscoLevel.combo_amount += 1
|
||||
var shell = load(shell_scene).instantiate()
|
||||
shell.flipped = flipped
|
||||
shell.times_kicked = times_kicked
|
||||
shell.old_entity = self.duplicate()
|
||||
if launch:
|
||||
AudioManager.play_sfx("kick", global_position)
|
||||
|
@@ -10,8 +10,8 @@ func _physics_process(delta: float) -> void:
|
||||
|
||||
func handle_collision() -> void:
|
||||
$HeadHitbox.position.y = (-length * 16) + 8
|
||||
$Collision.shape.size.y = (length * 16)
|
||||
$Collision.position.y = (-length * 8)
|
||||
$Collision.shape.size.y = (length * 16) - 2
|
||||
$Collision.position.y = -$Collision.shape.size.y / 2
|
||||
$BodyHitbox.position.y = $Collision.position.y
|
||||
|
||||
func handle_part_animation(delta: float) -> void:
|
||||
|
@@ -17,8 +17,8 @@ func _physics_process(delta: float) -> void:
|
||||
velocity.y += (15 / delta) * delta
|
||||
velocity.y = clamp(velocity.y, -INF, 150)
|
||||
if is_on_floor():
|
||||
velocity.y = -150
|
||||
if is_on_wall() or is_on_ceiling():
|
||||
velocity.y = -125
|
||||
if is_on_wall() or (abs(get_floor_normal().x) > 0 and is_on_ceiling()):
|
||||
hit()
|
||||
move_and_slide()
|
||||
|
||||
|
@@ -10,7 +10,7 @@ func _ready() -> void:
|
||||
owner.queue_free()
|
||||
return
|
||||
owner.show()
|
||||
if Checkpoint.passed:
|
||||
if owner.passed:
|
||||
sprite.hide()
|
||||
activated.show()
|
||||
|
||||
|
@@ -87,6 +87,7 @@ func player_exit(player: Player) -> void:
|
||||
exiting_door_id = -1
|
||||
can_enter = false
|
||||
LevelEditor.play_door_transition = false
|
||||
if same_scene_exiting_door != null: same_scene_exiting_door.get_node("Sprite").play("Idle")
|
||||
same_scene_exiting_door = null
|
||||
player.global_position = global_position
|
||||
player.recenter_camera()
|
||||
|
@@ -102,7 +102,8 @@ func in_game() -> void:
|
||||
run_player_check(i.owner)
|
||||
|
||||
func run_player_check(player: Player) -> void:
|
||||
if Global.player_action_pressed(get_input_direction(enter_direction), player.player_id) and can_enter and (player.is_on_floor() or enter_direction == 1 or player.gravity_vector != Vector2.DOWN) and player.state_machine.state.name == "Normal":
|
||||
# guzlad: Added support for characters with a hitbox height below 1.0 to enter pipes underwater
|
||||
if Global.player_action_pressed(get_input_direction(enter_direction), player.player_id) and can_enter and (player.is_on_floor() or enter_direction == 1 or player.gravity_vector != Vector2.DOWN or (!player.is_on_floor() and enter_direction == 3)) and player.state_machine.state.name == "Normal":
|
||||
can_enter = false
|
||||
pipe_entered.emit()
|
||||
DiscoLevel.can_meter_tick = false
|
||||
|
@@ -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
|
||||
|
@@ -3,6 +3,8 @@ extends Enemy
|
||||
|
||||
var moving := false
|
||||
|
||||
var moving_time := 0.0
|
||||
|
||||
const MOVE_SPEED := 192
|
||||
const AIR_MOVE_SPEED := 64
|
||||
|
||||
@@ -15,7 +17,7 @@ var can_kick := false
|
||||
|
||||
var player: Player = null
|
||||
|
||||
const COMBO_VALS := [500, 800, 1000, 2000, 4000, 5000, 8000, null]
|
||||
const COMBO_VALS := [100, 200, 400, 500, 800, 1000, 2000, 4000, 5000, 8000, null]
|
||||
|
||||
var wake_meter := 0.0 ## SMB1R IS WOKE
|
||||
|
||||
@@ -25,6 +27,8 @@ var can_update := true
|
||||
|
||||
var can_air_kick := false
|
||||
|
||||
var times_kicked := 0
|
||||
|
||||
func _ready() -> void:
|
||||
$Sprite.flip_v = flipped
|
||||
if flipped:
|
||||
@@ -40,14 +44,12 @@ func on_player_stomped_on(stomped_player: Player) -> void:
|
||||
return
|
||||
if not moving:
|
||||
direction = sign(global_position.x - stomped_player.global_position.x)
|
||||
kick()
|
||||
kick(stomped_player)
|
||||
else:
|
||||
DiscoLevel.combo_meter += 10
|
||||
moving = false
|
||||
AudioManager.play_sfx("enemy_stomp", global_position)
|
||||
stomped_player.enemy_bounce_off()
|
||||
if Global.current_game_mode == Global.GameMode.CHALLENGE and stomped_player.stomp_combo >= 10:
|
||||
die_from_object(stomped_player)
|
||||
stomped_player.enemy_bounce_off(true, moving_time > 0.1)
|
||||
|
||||
func block_bounced(_block: Block) -> void:
|
||||
velocity.y = -200
|
||||
@@ -59,19 +61,50 @@ func on_player_hit(hit_player: Player) -> void:
|
||||
return
|
||||
if not moving:
|
||||
direction = sign(global_position.x - hit_player.global_position.x )
|
||||
kick()
|
||||
kick(hit_player)
|
||||
else:
|
||||
hit_player.damage()
|
||||
|
||||
func award_score(award_level: int) -> void:
|
||||
if award_level >= 10:
|
||||
if Global.current_game_mode == Global.GameMode.CHALLENGE or Settings.file.difficulty.inf_lives:
|
||||
$ScoreNoteSpawner.spawn_note(10000)
|
||||
else:
|
||||
AudioManager.play_global_sfx("1_up")
|
||||
Global.lives += 1
|
||||
$ScoreNoteSpawner.spawn_one_up_note()
|
||||
else:
|
||||
$ScoreNoteSpawner.spawn_note(COMBO_VALS[award_level])
|
||||
|
||||
func get_kick_award(hit_player: Player) -> int:
|
||||
var award_level = hit_player.stomp_combo + 2
|
||||
if award_level > 10:
|
||||
award_level = 10
|
||||
# Award special amounts of points if close to waking up.
|
||||
if wake_meter > 7 - 0.04:
|
||||
award_level = 9
|
||||
elif wake_meter > 7 - 0.25:
|
||||
award_level = 5
|
||||
elif wake_meter > 7 - 0.75:
|
||||
award_level = 3
|
||||
return award_level
|
||||
|
||||
func kick() -> void:
|
||||
func kick(hit_player: Player) -> void:
|
||||
update_hitbox()
|
||||
DiscoLevel.combo_meter += 25
|
||||
moving = true
|
||||
moving_time = 0.0
|
||||
if can_air_kick:
|
||||
$ScoreNoteSpawner.spawn_note(8000)
|
||||
else:
|
||||
$ScoreNoteSpawner.spawn_note(400)
|
||||
award_score(get_kick_award(hit_player))
|
||||
AudioManager.play_sfx("kick", global_position)
|
||||
|
||||
# Limit the number of times you can kick the same shell.
|
||||
if Global.current_game_mode == Global.GameMode.CHALLENGE:
|
||||
times_kicked += 1
|
||||
if times_kicked >= 7:
|
||||
die_from_object(hit_player)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
handle_movement(delta)
|
||||
@@ -79,6 +112,7 @@ func _physics_process(delta: float) -> void:
|
||||
handle_block_collision()
|
||||
if moving:
|
||||
wake_meter = 0
|
||||
moving_time += delta
|
||||
$Sprite.play("Spin")
|
||||
else:
|
||||
combo = 0
|
||||
@@ -94,6 +128,7 @@ func handle_waking(delta: float) -> void:
|
||||
|
||||
func summon_original_entity() -> void:
|
||||
old_entity.global_position = global_position
|
||||
old_entity.times_kicked = times_kicked
|
||||
add_sibling(old_entity)
|
||||
queue_free()
|
||||
|
||||
@@ -105,17 +140,12 @@ func handle_block_collision() -> void:
|
||||
i.shell_block_hit.emit(self)
|
||||
|
||||
func add_combo() -> void:
|
||||
if combo >= 7:
|
||||
if Global.current_game_mode == Global.GameMode.CHALLENGE or Settings.file.difficulty.inf_lives:
|
||||
Global.score += 10000
|
||||
$ScoreNoteSpawner.spawn_note(10000)
|
||||
else:
|
||||
AudioManager.play_global_sfx("1_up")
|
||||
Global.lives += 1
|
||||
$ScoreNoteSpawner.spawn_one_up_note()
|
||||
else:
|
||||
$ScoreNoteSpawner.spawn_note(COMBO_VALS[combo])
|
||||
award_score(combo + 3)
|
||||
if combo < 7:
|
||||
combo += 1
|
||||
elif Global.current_game_mode == Global.GameMode.CHALLENGE and moving_time > 12.0:
|
||||
# Force limit on how long you can let a shell hit respawning enemies.
|
||||
die()
|
||||
|
||||
func update_hitbox() -> void:
|
||||
can_kick = false
|
||||
|
Reference in New Issue
Block a user