104 lines
2.5 KiB
GDScript
104 lines
2.5 KiB
GDScript
class_name Projectile
|
|
extends Area3D
|
|
|
|
const HEIGHT: float = 1
|
|
const MAX_STRETCH: float = 0.75
|
|
|
|
@export var _speed_stretch_factor: float = 100
|
|
|
|
@export var _hit_particles_scene: PackedScene
|
|
@export var _destroy_particles_scene: PackedScene
|
|
@export var _velocity_to_trail_rate: float = 0.5
|
|
|
|
@export_group("References")
|
|
@export var _model_base: Node3D
|
|
@export var _model_mesh: MeshInstance3D
|
|
@export var _trail_particles: GPUParticles3D
|
|
|
|
var _start_position: Vector3
|
|
var _velocity: Vector3
|
|
var _lifetime: float
|
|
var _size: float = 0.25
|
|
|
|
var _life_timer: float
|
|
|
|
|
|
func _ready() -> void:
|
|
_life_timer = _lifetime
|
|
global_position = _start_position
|
|
body_entered.connect(_on_body_entered)
|
|
_model_mesh.rotation = Vector3(
|
|
randf_range(0, TAU), randf_range(0, TAU), randf_range(0, TAU)
|
|
)
|
|
_model_mesh.scale = Vector3.ONE * _size
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
if _life_timer <= 0:
|
|
queue_free()
|
|
|
|
_life_timer -= delta
|
|
global_position += _velocity * delta
|
|
look_at(global_position + _velocity, Vector3.UP, true)
|
|
|
|
var speed := _velocity.length()
|
|
var speed_squash := clampf(speed / _speed_stretch_factor, 0, MAX_STRETCH)
|
|
_model_base.scale = Vector3(1 - speed_squash, 1 - speed_squash, 1 + speed_squash)
|
|
|
|
_trail_particles.amount = int(speed * _velocity_to_trail_rate)
|
|
|
|
|
|
func init(velocity: Vector3, start_position: Vector3, lifetime: float = 10) -> void:
|
|
_velocity = velocity
|
|
_start_position = start_position
|
|
_lifetime = lifetime
|
|
|
|
|
|
func hit(velocity: Vector3) -> void:
|
|
var hit_particles := (
|
|
_hit_particles_scene.instantiate() as Particles3DSelfDestructing
|
|
)
|
|
get_tree().get_root().add_child(hit_particles)
|
|
hit_particles.init(global_position, velocity)
|
|
set_velocity(velocity)
|
|
|
|
|
|
func set_velocity(velocity: Vector3) -> void:
|
|
_velocity = velocity
|
|
_life_timer = _lifetime
|
|
|
|
|
|
func _destroy() -> void:
|
|
var destroy_particles := (
|
|
_destroy_particles_scene.instantiate() as Particles3DSelfDestructing
|
|
)
|
|
get_tree().get_root().add_child(destroy_particles)
|
|
destroy_particles.init(global_position)
|
|
set_deferred("monitorable", false)
|
|
set_deferred("monitoring", false)
|
|
_model_base.visible = false
|
|
await get_tree().create_timer(5).timeout
|
|
queue_free()
|
|
|
|
|
|
|
|
|
|
func _on_body_entered(node: Node3D) -> void:
|
|
if node is Player:
|
|
queue_free()
|
|
var player := node as Player
|
|
player.stats.damage()
|
|
return
|
|
|
|
if node is CollisionObject3D:
|
|
var collision_node := node as CollisionObject3D
|
|
if collision_node.collision_layer & 1:
|
|
_destroy()
|
|
return
|
|
|
|
if node is CSGCombiner3D:
|
|
var collision_node := node as CSGCombiner3D
|
|
if collision_node.collision_layer & 1:
|
|
_destroy()
|
|
return
|