randomgeon/player/weapons/projectile_base.gd
Dan Baker 1a959fbc0c Improves lightning projectile behavior
Refactors the lightning projectile to handle collisions more effectively. It now stops upon hitting an enemy or object, triggers an explosion, and spawns child projectiles from the collision point.  The lightning bolt's collision shape is dynamically updated to match the remaining distance to the target or the collision point. Also adds more test enemies to the map for testing purposes.
2025-05-06 09:30:44 +01:00

101 lines
No EOL
2.9 KiB
GDScript

class_name ProjectileBase
extends Area2D
signal on_hit(projectile, target)
signal on_spawned(projectile)
signal on_destroyed(projectile)
@export var speed: float = 500.0
@export var damage: float = 10.0
@export var lifetime: float = 5.0
@export var direction: Vector2 = Vector2.RIGHT
@export var target_position: Vector2
@export var is_friendly: bool = true
# Modifier-related properties
var pierce_count: int = 0
var has_explosive_impact: bool = true
var explosion_projectile_count: int = 3
var explosion_projectile_damage_mult: float = 0.5
var explosion_projectile_speed: float = 300.0
var explosion_spread_angle: float = 360.0 # Full circle by default
# References
var source_weapon: RangedWeapon # Reference to the weapon that fired this
var lifetime_timer: Timer
# Add a variable to track the entity that triggered the explosion
var ignore_target = []
func _on_body_entered(body):
if ignore_target.has(body):
Log.pr("Ignoring body: ", body.name)
return
if body.is_in_group("enemies") and is_friendly:
Log.pr("Hit enemy: ", body.name)
# Deal damage to enemy
if body.has_method("take_damage"):
body.take_damage(damage)
# Emit signal for modifiers to react to
emit_signal("on_hit", self, body)
# Handle piercing
if pierce_count > 0:
pierce_count -= 1
else:
# Handle explosive impact
if has_explosive_impact:
# Store the target that triggered the explosion
ignore_target.append(body)
_trigger_explosion()
# Destroy the projectile
destroy()
func _trigger_explosion():
# Create the explosion VFX
# var explosion = preload("res://scenes/explosion_effect.tscn").instantiate()
# explosion.global_position = global_position
# get_tree().root.add_child(explosion)
# Spawn the additional projectiles
if explosion_projectile_count > 0:
_spawn_explosion_projectiles()
func _spawn_explosion_projectiles():
for i in range(explosion_projectile_count):
# Create a new projectile
Log.pr("Spawning explosion projectile")
var new_proj = duplicate()
Log.pr("New projectile: ", new_proj)
new_proj.global_position = global_position
# Calculate new direction based on spread
var random_angle = randf_range(0, 2 * PI)
var new_dir = Vector2.RIGHT.rotated(random_angle)
# Set properties for the new projectile
new_proj.direction = new_dir
new_proj.damage = damage * explosion_projectile_damage_mult
new_proj.speed = explosion_projectile_speed
# Clear explosive properties so we don't get infinite loops
new_proj.has_explosive_impact = true
new_proj.explosion_projectile_count = 1
# Pass the ignore_target to the new projectiles
new_proj.ignore_target = ignore_target
# Add to scene tree
get_tree().root.call_deferred("add_child", new_proj)
func set_projectile_scale(new_scale: Vector2):
# Set the scale of the projectile
self.scale = new_scale
func destroy():
emit_signal("on_destroyed", self)
queue_free()
func _on_lifetime_timeout():
destroy()