open-fpsz/entities/weapons/grenade_launcher/projectile.gd
2024-10-16 21:43:01 +00:00

60 lines
2.5 KiB
GDScript

# This file is part of open-fpsz.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
class_name GrenadeLauncherProjectile extends ArcProjectile
## The time before
@export var fuse_time : float = 1.
@export_range(0., 1.) var bounce_velocity_modifier: float = .24
var fuse_timer := Timer.new()
func _ready() -> void:
fuse_timer.wait_time = fuse_time
fuse_timer.one_shot = true
fuse_timer.autostart = true
add_child(fuse_timer)
# remove exceptions after a short time so that it can collide again with owner
get_tree().create_timer(.3).timeout.connect(func() -> void:
shape_cast.clear_exceptions())
func _physics_process(delta : float) -> void:
if not shape_cast: set_physics_process(false)
velocity += _gravity * delta
shape_cast.target_position = to_local(global_position + velocity * delta)
shape_cast.force_shapecast_update()
if shape_cast.is_colliding():
var collider: Node = shape_cast.get_collider(0)
var hit_point: Vector3 = shape_cast.get_collision_point(0)
# explode on player hit or when fuse timer is exhausted
if collider is Player or fuse_timer.is_stopped():
destroy(hit_point)
return
# bounce projectile
var hit_normal : Vector3 = shape_cast.get_collision_normal(0)
velocity = calc_bounce_velocity(velocity, hit_normal.normalized())
global_position = hit_point + hit_normal.normalized() * shape_cast.shape.radius
global_position += velocity * delta
else:
# move projectile
global_position += velocity * delta
## This method computes projectile bounce velocity.
func calc_bounce_velocity(_velocity: Vector3, hit_normal: Vector3) -> Vector3:
return mirror_vector_by_normal(_velocity, hit_normal.normalized()) * bounce_velocity_modifier
## This method computes reflected vector using the formula: R = V - 2 * (V dot N) * N
func mirror_vector_by_normal(_velocity: Vector3, hit_normal_unit_vector: Vector3) -> Vector3:
return _velocity - 2 * _velocity.dot(hit_normal_unit_vector) * hit_normal_unit_vector