randomgeon/player/weapons/ranged_weapon.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

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