Files
acrion-rog-client/scripts/parabolic_projectile.gd
Redsandy 7980e0add8 init
2026-01-18 20:56:24 +03:00

125 lines
5.2 KiB
GDScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends Projectile
class_name ParabolicProjectile
# Параболический снаряд для броска
@export var projectile_gravity: float = 200
@export var arc_height: float = 15.0 # Увеличена высота параболы
var target_position: Vector3 = Vector3.ZERO
var start_position: Vector3 = Vector3.ZERO
var travel_time: float = 0.0
var total_time: float = 0.0
func _ready():
start_position = global_position
# Проверяем, что target_position установлен
if target_position == Vector3.ZERO:
# Если не установлен, используем направление вперед
target_position = start_position + Vector3(0, 0, -10.0)
target_position.y = start_position.y
# Вычисляем горизонтальное расстояние
var horizontal_distance = Vector3(start_position.x, 0, start_position.z).distance_to(Vector3(target_position.x, 0, target_position.z))
# Вычисляем правильную траекторию для попадания в цель
var horizontal_dir = (target_position - start_position)
horizontal_dir.y = 0
# Если цель слишком близко (включая клик на самого игрока), устанавливаем минимальное расстояние и направление
if horizontal_distance < 1.0:
# Если направление нулевое или очень маленькое, используем направление вперед от игрока
if horizontal_dir.length() < 0.1:
# Используем направление камеры или направление вперед
var camera = get_viewport().get_camera_3d()
if camera:
var forward = -camera.global_transform.basis.z
forward.y = 0
horizontal_dir = forward.normalized()
else:
horizontal_dir = Vector3(0, 0, -1) # Направление по умолчанию
else:
horizontal_dir = horizontal_dir.normalized()
# Устанавливаем минимальное расстояние
horizontal_distance = 1.0
# Обновляем target_position на минимальном расстоянии от стартовой позиции
target_position = start_position + horizontal_dir * horizontal_distance
target_position.y = 0.0
else:
horizontal_dir = horizontal_dir.normalized()
# Время подъема до максимальной высоты
var time_to_peak = sqrt(2 * arc_height / projectile_gravity)
# Время полета вниз (примерно такое же)
var time_to_fall = time_to_peak
# Общее время полета по вертикали
var vertical_time = time_to_peak + time_to_fall
# Горизонтальная скорость должна обеспечить попадание в цель за время полета
var horizontal_speed = horizontal_distance / vertical_time
# Начальная вертикальная скорость для достижения нужной высоты
var vertical_speed = sqrt(2 * projectile_gravity * arc_height)
# Общее время полета
total_time = vertical_time
# Устанавливаем начальную скорость
velocity = horizontal_dir * horizontal_speed + Vector3.UP * vertical_speed
# Вызываем super._ready() после установки velocity
super._ready()
# Отключаем мониторинг коллизий при полете
monitoring = false
func _physics_process(delta):
if has_hit:
return
# Если velocity не установлена, не двигаемся
if velocity == Vector3.ZERO:
return
# Проверяем время жизни
lifetime_timer -= delta
if lifetime_timer <= 0:
if is_explosive:
explode(global_position)
else:
queue_free()
return
travel_time += delta
# Сохраняем предыдущую позицию для raycast (если понадобится)
previous_position = global_position
# Применяем гравитацию
velocity.y -= projectile_gravity * delta
# Движение снаряда
global_position += velocity * delta
# Проверяем, достигли ли цели
# Проверяем по Y координате (приземление) и по времени полета
# НЕ проверяем горизонтальное расстояние, так как это может сработать сразу при близких целях
if (global_position.y <= target_position.y + 0.3) and (travel_time >= total_time * 0.5):
# Включаем коллизию только при приземлении
monitoring = true
# Устанавливаем позицию точно в целевую точку
global_position = target_position
on_hit(target_position)
return
# Дополнительная проверка по времени полета (на случай, если снаряд не достиг земли)
if travel_time >= total_time * 1.2:
monitoring = true
global_position = target_position
on_hit(target_position)
return
# Не проверяем столкновения при полете - только движение