110 lines
3.1 KiB
GDScript
110 lines
3.1 KiB
GDScript
extends CharacterBody2D
|
|
@onready var earthaligner = $EarthAligner
|
|
@onready var player = get_tree().get_root().get_node("main/Player")
|
|
var moves = ["slam", "wave", "water_rise", "splash"]
|
|
@onready var next_move = choose_next_move()
|
|
@export var big_blob : PackedScene
|
|
|
|
var risen = 0
|
|
var attack_ready = true
|
|
var idle_dir : Vector2 = Vector2.ZERO
|
|
var idle_dir_remaining = 0
|
|
var idle_move = true
|
|
var target_pos = Vector2.ZERO
|
|
var damage = 1
|
|
var dead = false
|
|
signal grounded
|
|
|
|
|
|
func choose_next_move() -> String:
|
|
if $EnemyHurtbox.hp < 2 * $EnemyHurtbox.max_hp / 3 and risen == 0:
|
|
risen += 1
|
|
return "water_rise"
|
|
if $EnemyHurtbox.hp < $EnemyHurtbox.max_hp / 3 and risen == 1:
|
|
risen += 1
|
|
return "water_rise"
|
|
return ["slam", "wave", "splash"].pick_random()
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
if dead: return
|
|
up_direction = earthaligner.global_from_local(Vector2.UP)
|
|
if attack_ready:
|
|
attack_ready = false
|
|
call(next_move)
|
|
next_move = choose_next_move()
|
|
|
|
if(is_on_floor()):
|
|
grounded.emit()
|
|
|
|
if idle_move: move_idle(delta)
|
|
if($Hitbox.overlaps_body(player)):
|
|
player.hurt(damage, self.position - player.position)
|
|
move_and_slide()
|
|
|
|
func move_idle(delta : float):
|
|
idle_dir_remaining -= delta
|
|
if(idle_dir_remaining <= 0):
|
|
target_pos = player.position + player.earth_aligner.global_from_local(Vector2.UP) * 400
|
|
target_pos += randf_range(0, max(200, (target_pos - global_position).length())*0.25) * Vector2.from_angle(randf_range(0,TAU))
|
|
idle_dir = (target_pos - global_position).normalized()* max(200, (target_pos - global_position).length()) * 0.4
|
|
idle_dir_remaining = 0.5
|
|
velocity = idle_dir
|
|
|
|
func slam():
|
|
idle_move = false
|
|
velocity = up_direction * 500
|
|
await get_tree().create_timer(0.6).timeout
|
|
damage = 2
|
|
velocity = up_direction * -1500
|
|
await grounded
|
|
destroy_below()
|
|
damage = 1
|
|
velocity = up_direction * 500
|
|
await get_tree().create_timer(0.3).timeout
|
|
damage = 2
|
|
velocity = up_direction * -1500
|
|
await grounded
|
|
destroy_below()
|
|
damage = 1
|
|
velocity = up_direction * 35
|
|
await get_tree().create_timer(3).timeout
|
|
idle_move = true
|
|
attack_ready = true
|
|
|
|
func destroy_below():
|
|
if dead: return
|
|
for body in $DestructionChecker.get_overlapping_bodies():
|
|
if(body.has_method("destroy")): body.destroy()
|
|
|
|
func wave():
|
|
var angle = atan2(player.position.y, player.position.x)
|
|
var dir = randi_range(0, 1) * 2 - 1
|
|
get_tree().get_root().get_node("main/Water").create_tsunami(angle - dir*TAU/30, dir)
|
|
await get_tree().create_timer(4).timeout
|
|
attack_ready = true
|
|
|
|
func water_rise():
|
|
get_tree().get_root().get_node("main/Water").rise_water()
|
|
await get_tree().create_timer(5).timeout
|
|
attack_ready = true
|
|
|
|
func splash():
|
|
var blob_instance = big_blob.instantiate()
|
|
get_tree().get_root().get_node("main").add_child(blob_instance)
|
|
blob_instance.position = player.position
|
|
blob_instance.rotation = randf_range(0, TAU)
|
|
await get_tree().create_timer(5).timeout
|
|
attack_ready = true
|
|
|
|
|
|
func die():
|
|
dead = true
|
|
for child in get_children():
|
|
if not child is AudioStreamPlayer2D:
|
|
child.queue_free()
|
|
await $AudioStreamPlayer2D.finished
|
|
queue_free()
|
|
|
|
func _on_enemy_hurtbox_damage_taken() -> void:
|
|
if dead: return
|
|
$AudioStreamPlayer2D.play()
|