cave-of-dreams/scripts/slime.gd
2026-05-11 09:39:16 -04:00

122 lines
2.6 KiB
GDScript

extends CharacterBody3D
const SPEED = 2.5
const JUMP_VELOCITY = 4.5
var face_rotation = null
var face_left = false
var combatable = false
var health = 40
var mid_knockback = false
@onready var player = get_parent().get_node("Player")
enum {
STATE_IDLE,
STATE_JUMP,
STATE_LEAP,
STATE_HIT,
}
var state = STATE_IDLE
var state_timer = 1
var iframes = 0
@onready var game = get_parent()
@onready var camera = game.get_node("PlayerCamera")
func on_knockback() -> void:
state_timer = 99999
state = STATE_HIT
$Body/Animator.play("leap")
func _ready() -> void:
$Body.look_at(game.get_node("PlayerCamera").global_position)
$Body.rotation.x = 0
face_rotation = $Body.rotation.y
$Body/Animator.play("idle")
func _physics_process(delta: float) -> void:
if health <= 0:
queue_free()
return
state_timer -= delta
if state_timer < 0:
if state == STATE_IDLE:
state = STATE_JUMP
state_timer = 0.6
$Body/Animator.play("jump")
elif state == STATE_JUMP:
state = STATE_LEAP
state_timer = 99999
$Body/Animator.play("leap")
velocity = global_position.direction_to(player.global_position) * 3
velocity.y = 3
elif (state == STATE_LEAP) and is_on_floor():
state = STATE_IDLE
state_timer = randf_range(0.8, 1.5)
$Body/Animator.play("idle")
elif (state == STATE_HIT) and is_on_floor():
state = STATE_IDLE
state_timer = 0.5
$Body/Animator.play("idle")
if iframes > 0:
iframes -= delta
$Body.modulate.a = 0.5
else:
$Body.modulate.a = 1
$HealthLabel.text = str(health)
if not is_on_floor():
velocity += get_gravity() * delta
var viewport_half = (get_viewport().get_visible_rect().size / 2.0)
var player_position = camera.unproject_position(global_transform.origin)
print(viewport_half)
print(player_position)
if face_left:
$Body.rotation.y = face_rotation + deg_to_rad(180)
else:
$Body.rotation.y = face_rotation
var input_dir := Vector2.ZERO
if not combatable:
if input_dir.x > 0:
face_left = false
if input_dir.x < 0:
face_left = true
var direction = (camera.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if is_on_floor() and not mid_knockback:
if direction:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
else:
velocity.x = move_toward(velocity.x, 0, delta * 16)
velocity.z = move_toward(velocity.z, 0, delta * 16)
move_and_slide()
if player in $HitCollision.get_overlapping_bodies():
if player.iframes <= 0:
player.health -= 20
player.on_hit(self)
if mid_knockback: mid_knockback = false
$Shadow.global_position.y = $Floorcast.get_collision_point().y + 0.01