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": 3.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 Log.pr("Firing weapon") _spawn_projectile(global_position, direction, target_position) can_fire = false Log.pr("Cooldown", stats.get_stat("fire_rate")) fire_timer.start(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(): Log.pr("Fire timer timeout") can_fire = true