Refactored and documented boss code.

This commit is contained in:
RealMelwei 2025-10-11 20:02:47 +02:00
parent 60e32002c1
commit 8c11ee3000

View file

@ -5,18 +5,24 @@ var moves = ["slam", "wave", "water_rise", "splash"]
@export var big_blob : PackedScene @export var big_blob : PackedScene
@onready var water : Water = get_tree().get_root().get_node("main/Water") @onready var water : Water = get_tree().get_root().get_node("main/Water")
# How often water has been risen.
var risen = 0 var risen = 0
# Managing idle behavior between attacks.
var attack_ready = true var attack_ready = true
var idle_dir : Vector2 = Vector2.ZERO var idle_dir : Vector2 = Vector2.ZERO
var idle_dir_remaining = 0 var idle_dir_remaining = 0
var idle_move = true var idle_move = true
var target_pos = Vector2.ZERO var target_pos = Vector2.ZERO
var damage = 1 var damage = 1
var dead = false var dead = false
signal grounded signal grounded
signal slam_step_finished signal slam_step_finished
func choose_next_move() -> String: func choose_next_move() -> String:
# Water rises at 75% and 50% of remaining HP.
if $EnemyHurtbox.hp <= 3 * $EnemyHurtbox.max_hp / 4 and risen == 0: if $EnemyHurtbox.hp <= 3 * $EnemyHurtbox.max_hp / 4 and risen == 0:
risen += 1 risen += 1
return "water_rise" return "water_rise"
@ -25,10 +31,15 @@ func choose_next_move() -> String:
return "water_rise" return "water_rise"
var pool = ["splash"] var pool = ["splash"]
if not (position.length() - water.radius < 300 and randf()<0.75):
# Heavily decrease slam probability if boss height is low.
if not (position.length() - water.radius < 450 and randf()<0.75):
pool.append("slam") pool.append("slam")
# Heavily decrease wave probability if player is very high up.
if not (player.position.length() > water.radius + 900 and randf()<0.75): if not (player.position.length() > water.radius + 900 and randf()<0.75):
pool.append("wave") pool.append("wave")
return ["slam", "wave", "splash"].pick_random() return ["slam", "wave", "splash"].pick_random()
func _process(_delta: float) -> void: func _process(_delta: float) -> void:
@ -48,6 +59,7 @@ func _physics_process(delta: float) -> void:
move_and_slide() move_and_slide()
func move_idle(delta : float): func move_idle(delta : float):
# Pick a random target roughly above the player's head every 0.5 seconds.
idle_dir_remaining -= delta idle_dir_remaining -= delta
if(idle_dir_remaining <= 0): if(idle_dir_remaining <= 0):
target_pos = player.position + player.earth_aligner.global_from_local(Vector2.UP) * 400 target_pos = player.position + player.earth_aligner.global_from_local(Vector2.UP) * 400
@ -57,6 +69,8 @@ func move_idle(delta : float):
velocity = idle_dir velocity = idle_dir
func slam(): func slam():
# Move up, Slam Down, Repeat. Afterwards, linger for a moment.
# The slam destroys buildings.
idle_move = false idle_move = false
velocity = up_direction * 500 velocity = up_direction * 500
await get_tree().create_timer(0.6).timeout await get_tree().create_timer(0.6).timeout
@ -71,6 +85,8 @@ func slam():
attack_ready = true attack_ready = true
func slam_step(): func slam_step():
# End a downslam after ground is reached or 1.5 seconds have passed.
# Then destroy buildings hit.
damage = 2 damage = 2
velocity = up_direction * -1500 velocity = up_direction * -1500
grounded.connect(func(): slam_step_finished.emit()) grounded.connect(func(): slam_step_finished.emit())
@ -86,21 +102,24 @@ func destroy_below():
if(body.has_method("destroy")): body.destroy() if(body.has_method("destroy")): body.destroy()
func wave(): func wave():
var angle = atan2(player.position.y, player.position.x) # Raise a wave from the water at the boundary of the screen and move it towards the center.
var angle = player.position.angle
var dir = randi_range(0, 1) * 2 - 1 var dir = randi_range(0, 1) * 2 - 1
var speed = 3000/water.radius_base var speed = 3000 / water.radius_base
water.create_tsunami(angle - speed * dir*TAU/30, dir, speed) water.create_tsunami(angle - speed * dir * TAU/30, dir, speed)
await get_tree().create_timer(0.5).timeout await get_tree().create_timer(0.5).timeout
$Wave.play() $Wave.play()
await get_tree().create_timer(3.5).timeout await get_tree().create_timer(3.5).timeout
attack_ready = true attack_ready = true
func water_rise(): func water_rise():
# Increase the water level by 1 room height.
water.rise_water() water.rise_water()
await get_tree().create_timer(5).timeout await get_tree().create_timer(5).timeout
attack_ready = true attack_ready = true
func splash(): func splash():
# Form four small blobs around the player which merge into one.
var blob_instance = big_blob.instantiate() var blob_instance = big_blob.instantiate()
get_tree().get_root().get_node("main").add_child(blob_instance) get_tree().get_root().get_node("main").add_child(blob_instance)
blob_instance.position = player.position blob_instance.position = player.position
@ -110,13 +129,14 @@ func splash():
func die(): func die():
# Clear everything else, then wait for Audio Players to make sure sounds are not cut off.
dead = true dead = true
for child in get_children(): for child in get_children():
if not child is AudioStreamPlayer2D: if not child is AudioStreamPlayer2D:
child.queue_free() child.queue_free()
$DeathSound.play() $DeathSound.play()
await $DeathSound.finished await $DeathSound.finished
await get_tree().create_timer(3).timeout await get_tree().create_timer(1).timeout
get_tree().change_scene_to_file("res://ui/victory_screen/victory_screen.tscn") get_tree().change_scene_to_file("res://ui/victory_screen/victory_screen.tscn")
queue_free() queue_free()