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.
114 lines
3.2 KiB
GDScript
114 lines
3.2 KiB
GDScript
class_name RangedWeapon extends Node2D
|
|
|
|
signal projectile_spawned(projectile)
|
|
|
|
@export var projectile_scene: PackedScene
|
|
|
|
# Base stats - will be modified by modifiers
|
|
var base_stats = {
|
|
"damage": 10.0,
|
|
"fire_rate": 2.0,
|
|
"projectile_speed": 500.0,
|
|
"projectile_size": 1.0,
|
|
"projectile_lifetime": 1.0,
|
|
"projectile_quantity": 1,
|
|
"projectile_spread": 33,
|
|
"max_pierce": 0
|
|
}
|
|
|
|
# Components
|
|
var stats: ModifierManager
|
|
var can_fire: bool = true
|
|
var fire_timer: Timer
|
|
|
|
func _init() -> void:
|
|
stats = ModifierManager.new(base_stats)
|
|
Log.pr(stats)
|
|
add_child(stats)
|
|
|
|
# Setup fire timer
|
|
fire_timer = Timer.new()
|
|
add_child(fire_timer)
|
|
fire_timer.one_shot = true
|
|
|
|
projectile_scene = preload("res://assets/projectiles/projectile_lightning.tscn")
|
|
|
|
func _ready():
|
|
stats.connect("stats_updated", _on_stats_updated)
|
|
fire_timer.connect("timeout", _on_fire_timer_timeout)
|
|
|
|
# Initial update
|
|
_on_stats_updated()
|
|
|
|
func fire(direction: Vector2, target_position: Vector2):
|
|
if !can_fire:
|
|
return
|
|
|
|
_spawn_projectile(global_position, direction, target_position)
|
|
|
|
can_fire = false
|
|
fire_timer.start(1.0 / stats.get_stat("fire_rate"))
|
|
|
|
func _spawn_projectile(spawn_position: Vector2, spawn_direction: Vector2, target_position: Vector2):
|
|
# Get projectile quantity and spread from stats
|
|
var quantity = stats.get_stat("projectile_quantity")
|
|
var spread_angle = stats.get_stat("projectile_spread")
|
|
|
|
# Calculate the angle between each projectile
|
|
var angle_step = 0.0
|
|
if quantity > 1 and spread_angle > 0:
|
|
angle_step = spread_angle / (quantity - 1)
|
|
|
|
# Calculate starting angle (to center the spread)
|
|
var start_angle = - spread_angle / 2
|
|
|
|
# Spawn each projectile
|
|
for i in range(quantity):
|
|
var projectile = projectile_scene.instantiate()
|
|
projectile.global_position = spawn_position
|
|
projectile.target_position = target_position
|
|
|
|
# Calculate the direction with spread
|
|
var direction = spawn_direction
|
|
if quantity > 1:
|
|
var current_angle = start_angle + (i * angle_step)
|
|
direction = spawn_direction.rotated(deg_to_rad(current_angle))
|
|
|
|
projectile.direction = direction
|
|
|
|
# Apply stats to projectile
|
|
projectile.speed = stats.get_stat("projectile_speed")
|
|
projectile.damage = stats.get_stat("damage")
|
|
projectile.lifetime = stats.get_stat("projectile_lifetime")
|
|
projectile.source_weapon = self
|
|
|
|
# Set base size
|
|
var size = stats.get_stat("projectile_size")
|
|
projectile.set_projectile_scale(Vector2(size, size))
|
|
|
|
# Allow modifiers to directly modify the projectile
|
|
for modifier in stats.modifiers:
|
|
modifier.modify_projectile(projectile)
|
|
|
|
# Add to scene tree
|
|
if get_tree() and get_tree().get_root():
|
|
get_tree().get_root().add_child(projectile)
|
|
|
|
# Emit the spawn signal
|
|
if projectile.has_signal("on_spawned"):
|
|
projectile.emit_signal("on_spawned", projectile)
|
|
|
|
func add_modifier(modifier: Modifier):
|
|
Log.pr("Adding modifier: ", modifier)
|
|
stats.add_modifier(modifier)
|
|
|
|
func remove_modifier(modifier_id: String):
|
|
stats.remove_modifier(modifier_id)
|
|
|
|
func _on_stats_updated():
|
|
# Update any visual components based on new stats
|
|
# For example, if weapon appearance changes based on damage/fire rate
|
|
pass
|
|
|
|
func _on_fire_timer_timeout():
|
|
can_fire = true
|