2024-08-18 15:29:35 +00:00
|
|
|
class_name Crawler extends Entity
|
|
|
|
|
2024-08-18 17:12:13 +00:00
|
|
|
@onready var player = get_parent().get_parent().get_node("Player");
|
|
|
|
@onready var sprite = $AnimatedSprite2D
|
|
|
|
@onready var main_collider = $CollisionShape2D
|
|
|
|
@onready var whip = $WhipArea
|
2024-08-18 19:05:00 +00:00
|
|
|
@onready var speed_mult = 0
|
|
|
|
@onready var is_dying = false
|
|
|
|
@onready var explosion_sfx = $ExplosionSFX
|
|
|
|
@onready var death_timer = $DeathTimer
|
|
|
|
@onready var hurting = false
|
|
|
|
@onready var hurt_timer = $HurtTimer
|
|
|
|
@onready var attack_timer = $AttackTimer
|
|
|
|
@onready var recharge_timer = $Recharge
|
2024-08-18 17:12:13 +00:00
|
|
|
|
2024-08-18 15:29:35 +00:00
|
|
|
## Crawl towards the player but stay within striking distance and not super close
|
2024-08-18 17:12:13 +00:00
|
|
|
|
2024-08-18 19:05:00 +00:00
|
|
|
const HEALTH = 45
|
2024-08-18 17:12:13 +00:00
|
|
|
const SPEED_MULTIPLIER = 50
|
|
|
|
const ATTACK_DAMAGE = 20
|
|
|
|
|
2024-08-18 19:05:00 +00:00
|
|
|
var death_timer_started = false
|
|
|
|
var attacking = true
|
|
|
|
|
2024-08-18 17:12:13 +00:00
|
|
|
func _init() -> void:
|
|
|
|
super._init(HEALTH, SPEED_MULTIPLIER, ATTACK_DAMAGE)
|
|
|
|
|
2024-08-18 19:05:00 +00:00
|
|
|
func _ready() -> void:
|
|
|
|
whip.visible = false
|
2024-08-18 17:12:13 +00:00
|
|
|
|
|
|
|
func face_player():
|
|
|
|
var player_position = player.global_position
|
|
|
|
var crawler_position = global_position
|
|
|
|
|
|
|
|
if player_position.x > crawler_position.x and not sprite.flip_h:
|
|
|
|
sprite.flip_h = true
|
|
|
|
main_collider.position.x -= 62
|
|
|
|
position.x += 62
|
|
|
|
whip.position.x += 10
|
|
|
|
elif player_position.x < crawler_position.x and sprite.flip_h:
|
|
|
|
sprite.flip_h = false
|
|
|
|
main_collider.position.x += 62
|
|
|
|
position.x -= 62
|
|
|
|
whip.position.x -= 10
|
|
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
|
|
var distanceToPlayer = global_position.distance_to(player.global_position)
|
|
|
|
var desiredDistance = 70
|
|
|
|
|
2024-08-18 19:05:00 +00:00
|
|
|
if health <= 0 and !death_timer_started:
|
|
|
|
is_dying = true
|
|
|
|
death_timer_started = true
|
|
|
|
death_timer.start()
|
2024-08-18 17:12:13 +00:00
|
|
|
|
2024-08-18 19:05:00 +00:00
|
|
|
if !is_dying:
|
|
|
|
if !hurting:
|
|
|
|
if sprite.flip_h:
|
|
|
|
desiredDistance -= 69
|
|
|
|
face_player()
|
|
|
|
|
|
|
|
if distanceToPlayer > desiredDistance:
|
|
|
|
velocity.x = speed * speed_mult
|
|
|
|
face_player()
|
|
|
|
|
|
|
|
if not sprite.flip_h:
|
|
|
|
velocity.x *= -1
|
|
|
|
|
|
|
|
sprite.play("walk")
|
|
|
|
else:
|
|
|
|
if recharge_timer.is_stopped():
|
|
|
|
attacking = true
|
|
|
|
whip.visible = true
|
|
|
|
whip.connect("body_entered", whip_hit)
|
|
|
|
attack_timer.start()
|
|
|
|
|
|
|
|
if attacking and !attack_timer.is_stopped():
|
|
|
|
velocity.x = 0
|
|
|
|
sprite.play("Whip")
|
|
|
|
elif attacking and attack_timer.is_stopped():
|
|
|
|
recharge_timer.start()
|
|
|
|
whip.visible = false
|
|
|
|
whip.disconnect("body_entered", whip_hit)
|
|
|
|
attacking = false
|
|
|
|
|
2024-08-18 17:12:13 +00:00
|
|
|
|
2024-08-18 19:05:00 +00:00
|
|
|
if hurt_timer.is_stopped():
|
|
|
|
hurting = false
|
|
|
|
else:
|
2024-08-18 23:21:33 +00:00
|
|
|
sprite.play("jump away")
|
|
|
|
|
|
|
|
if speed_mult != 0:
|
|
|
|
move_and_slide()
|
2024-08-18 17:12:13 +00:00
|
|
|
else:
|
2024-08-18 19:05:00 +00:00
|
|
|
sprite.play("death")
|
|
|
|
explosion_sfx.play()
|
|
|
|
speed_mult = 0
|
|
|
|
if death_timer.is_stopped():
|
|
|
|
queue_free()
|
2024-08-18 17:12:13 +00:00
|
|
|
|
2024-08-18 19:05:00 +00:00
|
|
|
func charge() -> void:
|
|
|
|
speed_mult = 1
|
|
|
|
|
|
|
|
func hurt_anim():
|
|
|
|
hurting = true
|
|
|
|
hurt_timer.start()
|
|
|
|
|
|
|
|
func whip_hit(node: Node) -> void:
|
|
|
|
if node is Player:
|
|
|
|
node.health -= ATTACK_DAMAGE
|
|
|
|
node.take_knockback(50)
|
|
|
|
if node.has_method("hurt_anim"):
|
|
|
|
node.call("hurt_anim")
|