randomgeon/combat/weapons/_scripts/ranged_weapon_component.gd
Dan Baker fac3327c22 Improves projectile handling and modifiers
Refactors projectile spawning to allow for customized spawn locations and stat assignment.

Applies modifiers to projectiles at the time of spawning, enabling dynamic adjustments to projectile behavior.
2025-05-09 13:42:09 +01:00

84 lines
2.7 KiB
GDScript

@icon("res://assets/editor/64x64/fc1515.png")
extends Node2D
class_name RangedWeaponComponent
@export var stats: StatsComponent
@export var basic_projectile: PackedScene = preload("res://assets/projectiles/basic_projectile.tscn")
@onready var modifier_manager = $ModifierManager
@onready var projectile_scene: PackedScene = basic_projectile
var can_fire: bool = true
var cooldown: Timer
var projectile_spawn_location: Vector2
func _init() -> void:
cooldown = Timer.new()
add_child(cooldown)
cooldown.one_shot = true
func _ready() -> void:
Log.pr("RangedWeaponComponent initialized")
modifier_manager.set_stats(stats)
modifier_manager.connect("modifier_added", _on_modifier_added)
modifier_manager.connect("modifier_removed", _on_modifier_removed)
cooldown.connect("timeout", _on_fire_timer_timeout)
func add_modifier(modifier: Modifier) -> void:
modifier_manager.add_modifier(modifier)
func remove_modifier(modifier_id: String) -> void:
modifier_manager.remove_modifier(modifier_id)
func fire(direction: Vector2, target_position: Vector2) -> void:
if !can_fire:
return
spawn_projectile(direction, target_position)
can_fire = false
cooldown.start(1 / stats.get_stat("ranged.attack_rate"))
func set_projectile_scene() -> void:
projectile_scene = basic_projectile
modifier_manager.check_and_call("set_projectile_scene", [self])
## Get the projectile spawn location
## This defaults to the global position of the player
## but can be overridden by modifiers
func get_projectile_spawn_location() -> Vector2:
projectile_spawn_location = global_position
modifier_manager.check_and_call("get_projectile_spawn_location", [self])
return projectile_spawn_location
func spawn_projectile(spawn_direction: Vector2, target_position: Vector2) -> void:
Log.pr("Spawning projectile")
modifier_manager.check_and_call("spawn_projectile", [self])
## TODO: Handle multiple shots per fire
var projectile = projectile_scene.instantiate()
projectile.global_position = get_projectile_spawn_location()
projectile.target_position = target_position
projectile.set_stats(stats.duplicate())
projectile.source_weapon = self
var size = stats.get_stat("ranged.projectile_size")
projectile.set_projectile_scale(Vector2(size, size))
for modifier in modifier_manager.modifiers:
Log.pr("Adding modifier to projectile: ", modifier)
if projectile.has_method("add_modifier"):
projectile.add_modifier(modifier)
if get_tree() and get_tree().get_root():
get_tree().get_root().add_child(projectile)
func _on_modifier_added(_modifier: Modifier) -> void:
set_projectile_scene()
func _on_modifier_removed(_modifier: Modifier) -> void:
set_projectile_scene()
func _on_fire_timer_timeout() -> void:
can_fire = true