Godot Version
v4.2.2.stable.official [15073afe3]
Question
Hey all,
I’m currently developing a 2D platformer game. I have implemented fall damage, which utilizes the difference in player velocity right before hitting the ground and while on the ground.
The process works as intended when the player lands on the ground. The fall damage is calculated and deducted from the player’s health, and invincibility is applied for 3 seconds.
And if the player is invincible when hitting the ground from a height, the fall damage is ignored, which is also as intended.
The issue is when the player lands on a hazard (traps, damaging areas, etc.) before touching the ground.
It applies the damage from the hazard first. Then the player invincibility status is applied, ignoring the fall damage.
Is there any way to apply both fall damage and hazard damage at the same time, when the player lands on a hazard and becomes invincible afterward?
If the player is invincible when they land on a hazard from a height, both the fall damage and hazard damage should be ignored.
Scripts:
Player script:
var old_vel: float = 0
var velocity_difference: float
var fall_dmg: int
func apply_damage(damage_amount: int):
if is_shielded == false:
is_hurt = true
current_health -= damage_amount
go_invincible()
else:
SoundManager.play_clip(sound_player_hurt,SoundManager.SOUND_PLAYER_SHIELD_HIT)
if current_shield_amount >= damage_amount:
current_shield_amount -= damage_amount
else:
var remaining_dmg = damage_amount - current_shield_amount
current_shield_amount = 0
current_health -= remaining_dmg
go_invincible()
Signalmanager.on_player_hit.emit(current_shield_amount, current_health)
func _on_player_hitbox_area_entered(area):
if is_dead == true:
return
is_in_damaging_area = true
if invincible == true:
return
else:
if velocity_difference < -750:
return
else:
periodic_damage_check_timer.start()
if area.is_in_group("enemy_bullet"):
apply_damage(1)
if area.is_in_group("enemy_bomb_explosion"):
apply_damage(3)
if area.is_in_group("enemy_hitbox"):
apply_damage(1)
if area.is_in_group("hazard_normal_dmg"):
apply_damage(1)
func apply_fall_damage():
if invincible:
return
is_hurt = true
if velocity_difference < -750 and velocity_difference >= -850:
fall_dmg = roundi(max_health * 0.1)
elif velocity_difference < -850 and velocity_difference >= -950:
fall_dmg = roundi(max_health * 0.3)
elif velocity_difference < -950 and velocity_difference >= -1050:
fall_dmg = roundi(max_health * 0.5)
elif velocity_difference < -1050 and velocity_difference >= -1150:
fall_dmg = roundi(max_health * 0.7)
elif velocity_difference < -1150 and velocity_difference >= -1250:
fall_dmg = roundi(max_health * 0.9)
elif velocity_difference < -1250:
fall_dmg = roundi(max_health * 1)
current_health = current_health - fall_dmg
Signalmanager.on_player_hit.emit(current_shield_amount, current_health)
go_invincible()
Player State Machine > Fall state script
(“Player” is a reference to the Player node)
extends "State.gd"
func update(delta):
Player.apply_gravity(delta)
Player.animation_player.play("fall")
Player.velocity_difference = Player.velocity.y - Player.old_vel
if Player.velocity_difference < -750:
if Player.invincible == true:
pass
else:
Player.apply_fall_damage()
Player.old_vel = Player.velocity.y
player_movement()
if Player.is_on_floor() and Player.jump_input_actuation == false:
return STATES.IDLE
if Player.jump_input_actuation == true and can_coyote_jump == true:
return STATES.JUMP
if Player.shoot_input:
return STATES.AIR_SHOOT
if Player.throw_grenade_input:
return STATES.AIR_THROW
if Player.is_hurt:
return STATES.HURT
if Player.climbing:
return STATES.CLIMB_IDLE
if Player.is_dead == true:
return STATES.DEATH
return null
func enter_state():
//other code. not relevant to the question
func exit_state():
Player.velocity = Vector2.ZERO
//other code. not relevant to the question
Any help on this would be much appreciated.
Thank you in advance!